NOIP 2015 D1 T2 信息传递
题目的来源:NOIP 2015 D1 T2 信息传递
2996: [NOIP2015]信息传递 D1 T2 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 21 Solved: 7 [Submit][Status][Web Board] Description 有 n 个同学(编号为1到 n)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 i 的同学的信息传递对象是编号为 Ti 的同学。 游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮? Input 输入共2行。 第1行包含1个正整数 n,表示 n 个人。 第2行包含 n 个用空格隔开的正整数 T1,T2,……,Tn,其中第 i 个整数 Ti 表示编号为 i 的同学的信息传递对象是编号为 Ti 的同学, Ti ≤ n 且 Ti ≠ i。 数据保证游戏一定会结束。 Output 输出共1行,包含1个整数,表示游戏一共可以进行多少轮。 Sample Input 5 2 4 2 3 1 Sample Output 3 【数据规模与约定】 对于30%的数据,n≤200; 对于60%的数据,n≤2500; 对于100%的数据,n≤200000。
对于此题,开始由于学习了并查集,想用并查集,并采用路径压缩,可是发现这样会将关系弄得很乱,我最后也没理清思路,
最后参考别人的思路,在并查集的基础上去找到一个最小的环,
我们其实可以发现,在1-n每个人传递消息后就完成了信息传递,所以每个人父节点只用连一次,通过画图找规律我们还可以发现环的边数就是游戏的次数。
这样就可以写了
1 #include <bits/stdc++.h> 2 using namespace std; 3 int f[200010], g[200010]; 4 int n; 5 int find(int x, int &sum) 6 { 7 sum++; 8 if (x == f[x]) 9 return x; 10 else 11 return find(f[x], sum); 12 } 13 14 int main() 15 { 16 int i; 17 int ans = 0x3f3f3f3f; 18 cin >> n; 19 for (i = 1; i <= n; i++) 20 { 21 cin >> g[i]; 22 f[i] = i; 23 } 24 for (i = 1; i <= n; i++) 25 { 26 int sum = 0; 27 if (find(g[i], sum) == i) 28 { 29 ans = min(ans, sum); 30 } 31 else 32 { 33 f[i] = g[i]; 34 } 35 } 36 cout << ans; 37 return 0; 38 }
还要巩固加强,加油!

浙公网安备 33010602011771号