题目链接:https://www.luogu.org/problemnew/show/P2661#sub
一种利用并查集求最小环的做法:
对于每个同学看作一个点,每次信息传递是一条有向边,当出现最小环的时候就是所求游戏轮数。
那么我们在并查集上进行一些改动,用dep数组来保存路径的长度,即轮数。
如果有两个点的父节点相同,即组成了一个环。
注意的是要开一个last变量记录父节点(不记录就会在递归中被更新)。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 200001; 6 int fa[maxn], dep[maxn], n, ans = 0x7fffffff; 7 int find(int x) 8 { 9 if(fa[x]!=x) 10 { 11 int last = fa[x]; 12 fa[x] = find(fa[x]); 13 dep[x] += dep[last]; 14 } 15 return fa[x]; 16 } 17 void check(int a,int b) 18 { 19 int x = find(a); 20 int y = find(b); 21 if(x!=y){fa[x] = y; dep[a] = dep[b]+1;} 22 else ans = min(dep[a]+dep[b]+1,ans); 23 return; 24 } 25 int main() 26 { 27 int a; 28 scanf("%d",&n); 29 for(int i = 1; i <= n; i++) fa[i] = i; 30 for(int i = 1; i <= n; i++) 31 { 32 scanf("%d",&a); 33 check(i,a); 34 } 35 printf("%d",ans); 36 }