codeforce 698B Fix a Tree

来源:互联网 发布:淘宝发优惠怎么拿提成 编辑:程序博客网 时间:2024/06/06 05:04

题意:

给出n个点的父节点,问最少修改几个点能使整个图变成一棵树。


题解:

给出的图可能包括多个树、环,要使图变成树则要先将环解开,再将树合并。

用并查集保存树,再通过dfs判断是否存在环,解开环要注意一些细节。


#include<iostream>#include <stdio.h>#include <algorithm>#include <math.h>#include<stdlib.h>#include <string.h>#include<queue>#include<set>#include<map>#include<stack>#include<time.h>using namespace std;#define MAX_N 200005#define inf 0x7fffffff#define LL long long#define ull unsigned long long#define mod 10007LL INF=9e18;int n;int par[MAX_N];int ans[MAX_N];vector<int>G[MAX_N];int find(int x){    return x==par[x]?x:par[x]=find(par[x]);}void unite(int x,int y){    x = find(x);    y = find(y);    par[x] = y;}void init(){    for(int i=1;i<=n;i++)        par[i] = i;}bool dfs(int u,int v,int s){    for(int i=0;i<G[u].size();i++) {        if(G[u][i] == s || G[u][i] == v) {            return true;        }        else {            if(dfs(G[u][i], u, s))                return true;        }    }    return false;}int main(){    cin >> n;    init();    for(int i=1;i<=n;i++) {        int fa;        scanf("%d",&fa);        if(i != fa)            G[i].push_back(fa);        ans[i] = fa;        unite(i, fa);    }    int cnt = -1;    int fa;    int Fa = 0;    for(int i=1;i<=n;i++) {        if(par[i] == i) {            cnt++;            fa = i;            if(!dfs(i, 0, i))                Fa = i;        }    }    if(!Fa) {        cnt++;        ans[fa]=fa;    }    else {        fa = Fa;    }    for(int i=1;i<=n;i++) {        if(par[i] == i && i != fa) {            ans[i] = fa;            par[i] = fa;        }    }    cout << cnt << endl;    for(int i=1;i<=n;i++) {        printf("%d%c",ans[i],i==n?'\n':' ');    }}


0 0
原创粉丝点击