给出 n 个结点的父亲,问至少修改多少个结点的父亲,能使整张图变成
一棵树(根的父亲为自己),要求输出任一方案。
其中 1 ≤ n ≤ 200000
我是想做图论的 然后他可以用并查集来做ye? 用并查集来判断各种状态
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<cmath> #include<stack> #include<algorithm> using namespace std; #define ll long long #define rg register const int N=200000+5,pw=11,inf=0x3f3f3f3f,P=19650827; int n,m,ans=0,root=-1,a[N],f[N]; template <class t>void rd(t &x) { x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int find(int x){return f[x]==x?x:f[x]=find(f[x]);} void Union(int x,int y) {f[find(y)]=find(x);} int main() { //freopen("in.txt","r",stdin); //freopen("nocows.out","w",stdout); rd(n); for(int i=1;i<=n;++i){ rd(a[i]); f[i]=i; if(a[i]==i) root=i; } for(int i=1;i<=n;++i){ if(a[i]==root&&a[i]==i) continue; if(a[i]==i&&a[i]!=root){ a[i]=root,++ans; Union(a[i],root); } else if(a[i]!=i&&find(a[i])!=find(i)) Union(a[i],i); else if(a[i]!=i&&find(a[i])==find(i)){ if(!(root+1)) root=i; a[i]=root,++ans; Union(root,i); } } printf("%d ",ans); for(int i=1;i<=n;++i) printf("%d ",a[i]); return 0; }