codeforces 698B fix a tree 时间戳
把一个父亲数组变成棵树的最小改动。
一想就只有环或者森林,用时间戳,每次爆搜就行,要么剖环,要么连树。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <cstdlib> #include <vector> #include <set> #include <map> using namespace std; int parent[200100]; int time[200100]; int cnt=0,st=0,ans=0; void fun(int root) { time[root]=++cnt; while (!time[parent[root]]) { time[root]=cnt; root=parent[root]; } if (time[parent[root]]==cnt)//环或者是单棵树 { if (st==0) st=root;//本身没有根,新建一个根 parent[root]=st;//剖环进已遍历的树或者新建树,单棵树亦同 } else ans--; } int main() { int n; scanf ("%d",&n); for (int i=1;i<=n;i++) { scanf ("%d",&parent[i]); if (i==parent[i]) st=i; } for (int i=1;i<=n;i++) { if (!time[i]) fun(i),ans++; } printf ("%d\n",ans-1); for (int i=1;i<n;i++) printf ("%d ",parent[i]); printf ("%d\n",parent[n]); return 0; }