【luogu P2661 信息传递】 题解

题目链接: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 }    

 

posted @ 2018-03-07 10:28  Misaka_Azusa  阅读(203)  评论(0编辑  收藏  举报
Live2D