Fix a tree 拓扑消外向树

 http://codeforces.com/contest/698/problem/B

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int maxn=200005;
int fa[maxn],N,in[maxn],vis[maxn];
void tuopu(int x)
{
	while(!in[x]){
		vis[x]=1; 
		x=fa[x];
		in[x]--;
		if(vis[x]) break;
	}
}

int fcir(int x)
{
	while(!vis[x]){
		vis[x]=2; 
		x=fa[x];
	}
	return x;
}

int main()
{
	int fir=-1,ans=0;
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%d",&fa[i]);
		if(i==fa[i]){
			if(-1!=fir){
				ans++;
				fa[i]=fir;
				in[fir]++;
			}else fir=fa[i]; 
		}else	in[fa[i]]++;
	}
	//tuopu排序消去外相树 
	for(int i=1;i<=N;i++)
		if(!in[i]&&!vis[i]) tuopu(i);
	if(-1!=fir){
		for(int i=1;i<=N;i++){
			if(!vis[i]){
				ans++;
				int x=fcir(i);
				fa[x]=fir;
			}
		} 
	}else{
		for(int i=1;i<=N;i++){
			if(!vis[i]){
				vis[i]=2; 
				int x=fa[i];
				while(!vis[x]){
					vis[x]=2;
					x=fa[x];
				}
				fir=i;
				fa[i]=i;
				ans++;
				break;
			}
		}
		for(int i=1;i<=N;i++){
			if(!vis[i]){
				ans++;
				int x=fcir(i);
				fa[x]=fir;
			}
		} 
	}
	printf("%d\n",ans);
	for(int i=1;i<=N;i++)
		printf("%d ",fa[i]); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41755258/article/details/87940226