题目: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 ", ans); 58 return 0; 59 }