LOJ #2421. 「NOIP2015」信息传递 (求最小环

题目描述

有个同学(编号为 1 到)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为的同学的信息传递对象是编号为的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮?

输入

输入共 2行。

第 1行包含1个正整数n,表示n个人

第 2 行包含n 个用空格隔开的正整数T1 ,T 2 ,……,Tn , 其中第i个整数Ti表示编号为i

的同学的信息传递对象是编号为 T i 的同学,Ti≤n 且 Ti≠i。

数据保证游戏一定会结束

输出

输出共 1行,包含 1个整数,表示游戏一共可以进行多少轮。

样例

Sample Input
5

2 4 2 3 1

Sample Output
3

**
Hint
【输入输出样例 1 说明】

游戏的流程如图所示。当进行完第 3 轮游戏后,4 号玩家会听到 2 号玩家告诉他自己的生日,所以答案为 3。当然,第 3 轮游戏后,2 号玩家、3 号玩家都能从自己的消息来源得知自己的生日,同样符合游戏结束的条件。

对于 30%的数据,n≤ 200;

对于 60%的数据,n ≤ 2500;

对于 100%的数据,n ≤ 200000
**

题意

寻找最小的环, 可以直接用Tarjan找,当然也可用并查集进行维护

AC代码

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;

#define ls              st<<1
#define rs              st<<1|1
#define fst             first
#define snd             second
#define MP              make_pair
#define PB              push_back
#define LL              long long
#define PII             pair<int,int>
#define VI              vector<int>
#define CLR(a,b)        memset(a, (b), sizeof(a))
#define ALL(x)          x.begin(),x.end()
#define rep(i,s,e) for(int i=(s); i<=(e); i++)
#define tep(i,s,e) for(int i=(s); i>=(e); i--)

const int INF = 0x3f3f3f3f;
const int MAXN = 2e5+10;
const int mod = 1e9+7;
const double eps = 1e-8;

void fe() {
  #ifndef ONLINE_JUDGE
      freopen("in.txt", "r", stdin);
      freopen("out.txt","w",stdout);
  #endif
}
LL read()
{
   LL x=0,f=1;char ch=getchar();
   while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
   while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
   return x*f;
}

stack<int> S;
vector<int> E[MAXN];
int n, m, x;
int dfn[MAXN], low[MAXN], bl[MAXN];
int cnt, tot, ans;
bool vis[MAXN];

void tarjan(int u) {
    low[u] = dfn[u] = ++tot;
    S.push(u);
    vis[u] = true;
    for(int i = 0; i < E[u].size(); i++) {
        int v = E[u][i];
        if(!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if(vis[v]) {
            low[u] = min(low[u], dfn[v]);
        } 
    }
    if(low[u] == dfn[u]) {
        cnt = 0;
        while(true) {
            int v = S.top();
            S.pop();
            vis[v] = false;
            cnt++;
            if(v == u)
                break;
        }
    }
    if(cnt > 1)
        ans = min(ans, cnt);
}
int main(int argc, char const *argv[])
{
    cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> x;
        E[i].push_back(x);
    }   
    ans = INF;
    for(int i = 1; i <= n; i++) {
        if(!dfn[i]) 
            tarjan(i);
    } 
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wang2332/article/details/80614855