CodeForces 698B Fix a Tree

来源:互联网 发布:windows loader3.2.7 编辑:程序博客网 时间:2024/05/17 00:58

题意:给你n个数,第i个数代表点i连向点a[i],将这副图变成树,求最小改变边的数量,以及改变后的对应量。
题解:给出的n个数如果有一个点对应自己,那么这个环只有一个点,可以作为根。我们将有环的拆环,再接到根上。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <map>using namespace std;#define LL long long#define INF 0x3f3f3f3f#define PI acos(-1.0)#define E 2.71828#define MOD 1000000007#define N 200100int fa[N];int a[N];int n;void init(){    for(int i = 1; i <= n; i++)        fa[i] = i;}int Find(int x){    if(fa[x] != x)        fa[x] = Find(fa[x]);    return fa[x];}int main(){    scanf("%d",&n);    init();    int root = 0;    int ans = 0;    for(int i = 1; i <= n; i++)    {        scanf("%d",&a[i]);        if(a[i] == i)            root = i;        int fx = Find(a[i]);        int fy = Find(i);        if(fx != fy)            fa[fy] = fx;    }    for(int i = 1; i <= n; i++)    {        fa[i] = Find(i);        if(fa[i] == i)        {            if(root == 0)            {                root = i;                a[i] = i;                ans++;            }            else if(i != root)            {                a[i] = root;                ans++;            }        }    }    printf("%d\n",ans);    for(int i = 1; i <= n; i++)        printf("%d ",a[i]);    puts("");    return 0;}
0 0