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

时间:2022-01-04 20:44:09

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

题意:

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

思路:

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

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

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

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

 #include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<iostream> #define inf 0x7fffffff
using namespace std;
typedef long long LL;
typedef pair<int, int> pr; int n;
const LL maxn = 2e5 + ;
int to[maxn];
int fa[maxn], rnk[maxn]; void init()
{
for(int i = ; i <= n; i++){
fa[i] = i;
rnk[i] = ;
}
} int ffind(int x)
{
if(fa[x] == x)return x;
int last = fa[x];
fa[x] = ffind(fa[x]);
rnk[x] += rnk[last];
return fa[x];
} int main()
{
scanf("%d", &n);
init();
int ans = maxn;
for(int i = ; i <= n; i++){
scanf("%d", &to[i]);
int fx = ffind(i), fy = ffind(to[i]);
if(fx != fy){
fa[fx] = fy;
rnk[i] = rnk[to[i]] + ;
}
else{
ans = min(ans, rnk[i] + rnk[to[i]] + );
}
}
printf("%d\n", ans);
return ;
}