F

题目链接

题目大意

给n个结点的图,给出每个点的父结点。问最多修改几个父亲节点,让它们形成一棵树。

题目思路

如果图中并不是全部是是环,那么就随意取一棵树的根节点当作总根节点

如果全部是环,随意取一个环上的点当作根节点即可

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
int a[maxn];
int fa[maxn],sz1[maxn],sz2[maxn];
int findd(int x){
    return x==fa[x]?x:fa[x]=findd(fa[x]);
}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        fa[i]=i;
        sz1[i]=1;
        // 点数
        sz2[i]=0;
        // 边数
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(i==a[i]) continue;
        int x=findd(i),y=findd(a[i]);
        if(x==y){
            sz2[x]++;
        }else{
            fa[x]=y;
            sz1[y]+=sz1[x];
            sz2[y]+=sz2[x]+1;
        }
    }
    int tree=-1,ans=0;
    for(int i=1;i<=n;i++){
        int x=findd(i);
        if(sz1[x]==sz2[x]+1){
            tree=x;
            break;
        }
    }
    if(tree==-1){
        tree=findd(1);
    }
    // tree为根节点
    for(int i=1;i<=n;i++){
        int x=findd(i);
        if(a[x]!=tree){
            a[x]=tree;
            ans++;
        }
    }
    printf("%d
",ans);
    for(int i=1;i<=n;i++){
        printf("%d ",a[i]);
    }

    return 0;
}

卷也卷不过,躺又躺不平
原文地址:https://www.cnblogs.com/hunxuewangzi/p/14620287.html