题意:给定一棵n个点的树,要求将一条可以随意标号的链通过若干次操作变成这棵树
一次操作是指若v不为根且v的父亲不为根,则将v以及v的子树移到v的父亲的父亲上
要求给出标号方案,操作次数以及方案
n<=1e5
思路:考虑最小的操作次数,每一次操作可能使树的最大深度+1,事实上也存在这样的构造方案:
找到从根下来的最长链,找到深度最大的分叉点u,设最长链的后继为v,u的另一个儿子为w,则将v变成w的儿子
具体实现的时候可以用cnt记录当前节点上一个兄弟的最后一条链的深度
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef long double ld; 7 typedef pair<int,int> PII; 8 typedef pair<ll,ll> Pll; 9 typedef vector<int> VI; 10 typedef vector<PII> VII; 11 typedef pair<ll,ll>P; 12 #define N 200010 13 #define M 200010 14 #define INF 1e9 15 #define fi first 16 #define se second 17 #define MP make_pair 18 #define pb push_back 19 #define pi acos(-1) 20 #define mem(a,b) memset(a,b,sizeof(a)) 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 23 #define lowbit(x) x&(-x) 24 #define Rand (rand()*(1<<16)+rand()) 25 #define id(x) ((x)<=B?(x):m-n/(x)+1) 26 #define ls p<<1 27 #define rs p<<1|1 28 29 const ll MOD=1e9+7,inv2=(MOD+1)/2; 30 double eps=1e-6; 31 int dx[4]={-1,1,0,0}; 32 int dy[4]={0,0,-1,1}; 33 34 int head[N],vet[N],nxt[N],f[N],d[N],c[N],id[N],son[N],tot,cnt,ans,s; 35 36 int read() 37 { 38 int v=0,f=1; 39 char c=getchar(); 40 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 41 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 42 return v*f; 43 } 44 45 void add(int a,int b) 46 { 47 nxt[++tot]=head[a]; 48 vet[tot]=b; 49 head[a]=tot; 50 } 51 52 void dfs(int u) 53 { 54 id[++s]=u; 55 rep(i,1,cnt) c[++ans]=u; 56 cnt=0; 57 int e=head[u]; 58 while(e) 59 { 60 int v=vet[e]; 61 if(v!=son[u]) dfs(v); 62 e=nxt[e]; 63 } 64 if(son[u]) dfs(son[u]); 65 cnt++; 66 } 67 68 int main() 69 { 70 int n=read(); d[1]=1; 71 rep(i,1,n) head[i]=0; 72 tot=0; 73 rep(i,2,n) 74 { 75 int x=read()+1; 76 f[i]=x; 77 d[i]=d[x]+1; 78 add(x,i); 79 } 80 int k=1; 81 rep(i,1,n) 82 if(d[i]>d[k]) k=i; 83 while(k>1) 84 { 85 son[f[k]]=k; 86 k=f[k]; 87 } 88 s=ans=0; 89 dfs(1); 90 rep(i,1,n) printf("%d ",id[i]-1); 91 printf(" "); 92 printf("%d ",ans); 93 rep(i,1,ans) printf("%d ",c[i]-1); 94 return 0; 95 }