[并查集][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 }