Codeforces 698C. Fix a Tree (并查集)

来源:互联网 发布:打印发票软件 编辑:程序博客网 时间:2024/05/21 14:48

题目链接

简单题意

给出一张图,求最小的改变使他变为一个有根树,每个节点至多一个父亲节点

思路

因为至多有一个父亲节点,所以在每一个联通子图中至多有一个环。当输入中没有已有的根时,即所有的联通子图都有环,最小的改变就是打破每个环,并随意选一个为根,如果输入中已有根,则最小的改动就是打破环并把环接到某一个根上,并把剩下的根也接到这个根上。

判环和根可以用并查集很方便的处理

代码

#include <bits/stdc++.h>using namespace std;const int maxn = 2e5+10;int cy[maxn];int fa[maxn];int Find(int x){    return fa[x] == x ? x : fa[x] = Find(fa[x]);}int cnt = 0;int tmp = 0;int Union(int x ,int y){    int a = Find(x);    int b = Find(y);    if(a == b){        cy[x] = 0;        if(x == y ) tmp = x;        cnt ++;    }    else cy[x] = y;    fa[b] = a;}int main(){    int n,t;    cin >>n;    for(int i = 0 ; i <= n ; i ++){        fa[i] = i;    }    int f = 0;    for(int i = 0 ; i < n ; i ++){        scanf("%d",&t);        Union(i+1,t);        if(t == i+1)            f = 1;    }    printf("%d\n",cnt - f);    for(int i = 1 ; i <= n ; i ++){        if(cy[i])            printf("%d ",cy[i]);        else if(tmp)            printf("%d ",tmp);        else{            tmp = i;            printf("%d ",tmp);        }    }}
0 0
原创粉丝点击