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 }

还要巩固加强,加油!

posted @ 2021-01-18 23:37  IChase  阅读(34)  评论(0)    收藏  举报
Live2D