列表

详情


OR97. 狙击手

描述

N个狙击手在进行生死搏斗,每位狙击手各瞄准了一个目标,一旦开枪就会将被瞄准的目标消灭,被消灭的狙击手无法再开枪。已知任意两个狙击手不会同时开枪,但不知道他们的开枪顺序,所以无法确定最后哪些狙击手会存活下来。
请你求出最少可能存活多少个狙击手,最多可能存活多少个狙击手。

输入描述

第一行一个正整数N 接下来一行N个正整数,第i个数字Ti表示第i个狙击手瞄准了第Ti个狙击手,注意可能存在Ti=i

输出描述

两行,第一行是最少存活的狙击手的数量,第二行是最多存活的狙击手的数量

示例1

输入:

8
2 3 2 2 6 7 8 5

输出:

3
5

说明:

样例解释: 最少存活的情况:2开枪消灭3,1开枪消灭2,7开枪消灭8,6开枪消灭7,5开枪消灭6,最后1, 4, 5存活。 最多存活的情况:1开枪消灭2,5开枪消灭6,7开枪消灭8,最后1,3,4,5,7存活。 数据约定: 20% N≤10 50% N≤10000 100% N≤1000000,1≤Ti≤N

原站题解

C++ 解法, 执行用时: 130ms, 内存消耗: 12500KB, 提交时间: 2020-12-28

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <sstream>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
  
int target[1000005];
bool visit[1000005];
int father[1000005];
  
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, ans;
    int the_next;
    cin >> n;
    for (int i = 1; i < n + 1; i++)
    {
        cin >> target[i];
        father[target[i]]++;
    }
  
    for (int i = 1; i < n + 1; i++)
    {
        if (father[i] == 0)
        {
            visit[i] = true;
            ans++;
            the_next = target[i];
            while (!visit[the_next])
            {
                visit[the_next] = true;
                the_next = target[the_next];
            }
        }
    }
  
    for (int i = 1; i < n + 1; i++)
    {
        if (visit[i] || i == target[i])continue;
        visit[i] = true;
        ans++;
        the_next = target[i];
        while (!visit[the_next])
        {
            visit[the_next] = true;
            the_next = target[the_next];
        }
    }
    cout << ans << endl;
  
    memset(visit, false, sizeof(visit));
    ans = 0;
    queue<int> line;
    for (int i = 1; i < n + 1; i++)
        if (father[i] == 0)
            line.push(i);
    int head;
    while (!line.empty())
    {
        head = line.front();
        line.pop();
        visit[head] = true;
        ans++;
        the_next = target[head];
        if (!visit[the_next])
        {
            visit[the_next] = true;
            the_next = target[the_next];
            father[the_next]--;
            if (father[the_next] == 0)
            {
                line.push(the_next);
            }
        }
    }
  
    int lens;
    for (int i = 1; i < n + 1; i++)
    {
        if (visit[i] || i == target[i])continue;
        visit[i] = true;
        lens = 1;
        the_next = target[i];
        while (!visit[the_next])
        {
            lens += 1;
            visit[the_next] = true;
            the_next = target[the_next];
        }
        ans += (lens >> 1);
    }
    cout << ans << endl;
    return 0;
}

C++ 解法, 执行用时: 134ms, 内存消耗: 12536KB, 提交时间: 2020-10-31

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <sstream>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
  
int target[1000005];
bool visit[1000005];
int father[1000005];
  
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, ans;
    int the_next;
    cin >> n;
    for (int i = 1; i < n + 1; i++)
    {
        cin >> target[i];
        father[target[i]]++;
    }
  
    for (int i = 1; i < n + 1; i++)
    {
        if (father[i] == 0)
        {
            visit[i] = true;
            ans++;
            the_next = target[i];
            while (!visit[the_next])
            {
                visit[the_next] = true;
                the_next = target[the_next];
            }
        }
    }
  
    for (int i = 1; i < n + 1; i++)
    {
        if (visit[i] || i == target[i])continue;
        visit[i] = true;
        ans++;
        the_next = target[i];
        while (!visit[the_next])
        {
            visit[the_next] = true;
            the_next = target[the_next];
        }
    }
    cout << ans << endl;
  
    memset(visit, false, sizeof(visit));
    ans = 0;
    queue<int> line;
    for (int i = 1; i < n + 1; i++)
        if (father[i] == 0)
            line.push(i);
    int head;
    while (!line.empty())
    {
        head = line.front();
        line.pop();
        visit[head] = true;
        ans++;
        the_next = target[head];
        if (!visit[the_next])
        {
            visit[the_next] = true;
            the_next = target[the_next];
            father[the_next]--;
            if (father[the_next] == 0)
            {
                line.push(the_next);
            }
        }
    }
  
    int lens;
    for (int i = 1; i < n + 1; i++)
    {
        if (visit[i] || i == target[i])continue;
        visit[i] = true;
        lens = 1;
        the_next = target[i];
        while (!visit[the_next])
        {
            lens += 1;
            visit[the_next] = true;
            the_next = target[the_next];
        }
        ans += (lens >> 1);
    }
    cout << ans << endl;
    return 0;
}

上一题