洛谷P2661 信息传递【并查集】

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

题意:

有一个有向图,问最小环的的大小。

思路:

明明是图的遍历,但是bfs会T。第二组下下来的数据n居然是12位的我也搞不懂怎么这么奇怪。

总之用并查集可以做。这个题每个点只有一个出边。

如果有一条从x到y的有向边,那么y就是x的父亲,并查集合并之后这些点的联通关系就可以找到了。

加入一条边后,如果已经是一个集合的了就说明有一个环。同时还需要维护一下节点到祖先的路径长度。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<cmath> 
 9 #include<stack>
10 #include<queue>
11 #include<iostream>
12 
13 #define inf 0x7fffffff
14 using namespace std;
15 typedef long long LL;
16 typedef pair<int, int> pr;
17 
18 int n;
19 const LL maxn = 2e5 + 5;
20 int to[maxn];
21 int fa[maxn], rnk[maxn];
22 
23 void init()
24 {
25     for(int i = 1; i <= n; i++){
26         fa[i] = i;
27         rnk[i] = 0;
28     }
29 }
30 
31 int ffind(int x)
32 {
33     if(fa[x] == x)return x;
34     int last = fa[x];
35     fa[x] = ffind(fa[x]);
36     rnk[x] += rnk[last];
37     return fa[x];
38 }
39 
40 
41 int main()
42 {
43     scanf("%d", &n);
44     init();
45     int ans = maxn;
46     for(int i = 1; i <= n; i++){
47         scanf("%d", &to[i]);
48         int fx = ffind(i), fy = ffind(to[i]);
49         if(fx != fy){
50             fa[fx] = fy;
51             rnk[i] = rnk[to[i]] + 1;
52         }
53         else{
54             ans = min(ans, rnk[i] + rnk[to[i]] + 1);
55         }
56     }
57     printf("%d\n", ans);
58     return 0; 
59 }

 

posted @ 2019-06-20 10:18  wyboooo  阅读(218)  评论(0编辑  收藏  举报