Fix a Tree

来源:互联网 发布:迪奥旷野香水知乎 编辑:程序博客网 时间:2024/06/03 14:26

`这里写图片描述

主要有三个步骤 1、确定根节点root2、分解环 3 连接子树

  1明确是否有可行根节点,有随便找一个;没有:从环中招一个

  2为了操作方便,使用并查集寻找环,并将找到第一个环的任意一个节点作为根节点。

 3 在确定了根节点之后,如果遇到其他可行根节点,直接连接到已确定根节点即可,就是连接子树的操作。
  
 用t数组来prime找环,依此修改tree数组 

这里写代码片#include<cstdio>#include<iostream>#include<cstring>using namespace std;int tree[200020],t[200020];int findroot(int x){    return x==t[x]?x:t[x]=findroot(t[x]);}void prime(int x,int y){    int fx=findroot(x);    int fy=findroot(y);    t[fx]=fy;}int main(){    int n,i,j,ans,root;    while(~scanf("%d",&n)&&n>=2)    {        root=-1;        ans=0;        for(i=1;i<=n;i++)        {            scanf("%d",&tree[i]);            t[i]=i;            if(i==tree[i])                root=i;        }        for(i=1;i<=n;i++)        {            if(tree[i]==i&&i==root)                continue;            else if(tree[i]==i&&i!=root)            {                ans++;                tree[i]=root;                prime(i,root);            }            else if(tree[i]!=i&&findroot(tree[i])!=findroot(i))                prime(i,tree[i]);            else if(tree[i]!=i&&findroot(tree[i])==findroot(i))            {                if(root==-1)                {                    root=i;                }                tree[i]=root;                ans++;                prime(i,root);            }        }        printf("%d\n",ans);        for(i=1;i<=n;i++)        {            printf("%d",tree[i]);            if(i!=n)printf(" ");            else printf("\n");        }    }    return 0;}
0 0