[并查集][NOIP2015]信息传递

信息传递

题目描述

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

输入

输入文件名为 message.in。
输入共 2 行。
第 1 行包含 1 个正整数 N,表示 N个人。
第 2 行包含 N个用空格隔开的正整数 T1, T2, … … , Tn,其中第i个整数Ti表示编号为 i
的同学的信息传递对象是编号为 Ti 的同学, Ti ≤ n 且 Ti ≠ i
数据保证游戏一定会结束。

输出

输出文件名为 message.out。
输出共 1 行,包含 1 个整数,表示游戏一共可以进行多少轮。

样例输入

5
2 4 2 3 1

样例输出

3

提示

用并查集找到最小环就好啦QAQQ

还是蛮简单的一道题qwqq

上代码吧~:

 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 int fa[200002], d[200002], n, minn, last;
 5 
 6 int read(){
 7     int x = 0, f = 1; 
 8     char ch = getchar(); 
 9     while (ch < '0' || ch > '9') {
10         if (ch == '-') {
11             f = -1; 
12         }
13         ch = getchar(); 
14     }
15     while (ch >= '0' && ch <= '9') {
16         x = x * 10 + ch - '0'; 
17         ch = getchar(); 
18     }
19     return x * f; 
20 }
21 
22 int find(int x){
23     if (fa[x] != x) {
24         int last = fa[x];
25         fa[x] = find(fa[x]);
26         d[x] += d[last]; 
27     }
28     return fa[x];
29 }
30 
31 void check(int a, int b){
32     int x = find(a), y = find(b); 
33     if (x != y) {
34         fa[x] = y; 
35         d[a] = d[b] + 1;
36     } 
37     else {
38         minn = std::min(minn, d[a] + d[b] + 1);
39     }
40     return;
41 }
42 
43 int main(){
44     int i, t;
45     n = read(); 
46     for (i = 1; i <= n; i++) {
47         fa[i] = i; 
48     }
49     minn = 0x7777777;
50     for (i = 1; i <= n; i++) {
51         t = read(); 
52         check(i, t); 
53     }
54     printf("%d",minn);
55     return 0;
56 }

猜你喜欢

转载自www.cnblogs.com/GldHkkowo/p/8921446.html