洛谷 P2661 信息传递

 

题目链接:https://www.luogu.org/problemnew/show/P2661

题目描述:

有n个同学(编号为1到n )正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,
其中,编号为i的同学的信息传递对象是编号为Ti​的同学。

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

思路:可以用并查集求最小回路。可以比作有向图,每个点出度都为1,即每个点只有一条边可以到其他点。
如果有一个传递关系:A -> B, B->C, C->A,说明要传递3次才能有人会被告知自己的生日,那么在并查集可以fa[C] = B ,f[B] = A, f[A] = A,
模拟了信息完全的的传递,而且“当有人从别人口中得知自己的生日时,游戏结束”,那么我们要维护一个最小值,即最少传递回合,满足题意。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <vector>
 6 #include <string>
 7 using namespace std;
 8  
 9 typedef long long LL;
10 #define inf (1LL << 30) - 1
11 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
12 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
13 #define per(i,j,k) for(int i = (j); i >= (k); i--)
14 #define per__(i,j,k) for(int i = (j); i > (k); i--)
15 
16 const int N = (int)2e5 + 10;
17 int fa[N];
18 int G[N];
19 int n,v;
20 int ans = inf;
21 
22 void init(){
23     rep(i,1,n) fa[i] = i;
24 }
25 
26 int search(int x, int& cnt){
27 
28     ++cnt; //回路的深度
29     if(fa[x] == x) return x;
30     else return search(fa[x], cnt);
31 }
32 
33 int main(){
34  
35     ios::sync_with_stdio(false);
36     cin.tie(0);
37 
38      cin >> n;
39     init();
40 
41     rep(i,1,n){
42         
43         int cnt = 0;
44         
45         cin >> v;
46         if(search(v,cnt) == i){
47             ans = min(ans,cnt); //找到了回路,并维护最小回路
48         }
49         else {
50             fa[i] = v;// i -> v
51         }
52     }
53     cout << ans << endl;
54     getchar();getchar();
55     return 0;
56 }

 

posted @ 2019-07-19 17:43  SummerMingQAQ  阅读(218)  评论(0编辑  收藏  举报