思路:
自己写的时候炸了好多次。没找到毛病,感觉是因为单点处理和环处理的时候没处理好。下面给AC思路
在合并的时候就要时刻判断这个点 是否是个根(环的根 或者是 单点根都算)。
先说一种特殊情况, 如果有单点,有环。我们需要拆环连到点上,而不能将环独立,将点连在环上。各位可以自己算算步骤,多了一步
因此,打标记的时候先找是否有单点,如果没有再拆环。
好了关键问题说完了,下面上代码
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int father[200005];
int relation[200005];
int cir[200005];
int a[200005];
int flag=0;
int n,m;
int sum=0;
int find(int x)
{
if(father[x]!=x)
father[x]=find(father[x]);
return father[x];
}
int Union(int x,int y)
{
int root1=find(x);
int root2=find(y);
if(root1!=root2)
{
father[root2]=root1;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
father[i]=i;
}
int cnt=0;
for(int i=1;i<=n;i++)
{
int root1=find(i);
int root2=find(a[i]);
if(root1==root2)
{
if(flag==0&&i==a[i])
{
flag=i;
}
else
cir[++cnt]=i;
}
else
Union(a[i],i);
}
if(flag==0)
{
flag=cir[1];
}
for(int i=1;i<=cnt;i++)
{
sum++;
a[cir[i]]=flag;
}
cout<<sum<<endl;
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
}