BZOJ2815: [ZJOI2012]灾难
支配树太好写了。支配树的内容建议看原论文。
#include<bits/stdc++.h> #define FOR(v,a)\ for(int v##0=0,v=0;v##0<a.size()&&((v=a[v##0])||1);++v##0) using namespace std; const int N=65536; vector<int>t1[N],t2[N],buc[N]; int n,f[N],par[N],semi[N],ver[N],dom[N],anc[N],lab[N]; void dfs(int u){ semi[u]=++n; ver[n]=u; FOR(v,t1[u]){ if(!semi[v]){ par[v]=u; dfs(v); } t2[v].push_back(u); } } int eval(int u){ if(anc[anc[u]]){ eval(anc[u]); if(semi[lab[anc[u]]]<semi[lab[u]]) lab[u]=lab[anc[u]]; anc[u]=anc[anc[u]]; } return lab[u]; } void sol(int r){ dfs(r); for(int i=1;i<=n;++i) lab[i]=i; for(int i=n;i>=2;--i){ int u=ver[i]; FOR(v,t2[u]){ int w=eval(v); if(semi[w]<semi[u]) semi[u]=semi[w]; } buc[ver[semi[u]]].push_back(u); anc[u]=par[u]; FOR(v,buc[par[u]]){ int w=eval(v); dom[v]=semi[w]<semi[v]?w:par[u]; } buc[par[u]].clear(); } for(int i=2;i<=n;++i){ int u=ver[i]; if(dom[u]!=ver[semi[u]]) dom[u]=dom[dom[u]]; } } int main(){ struct{ operator int(){ int x=0,c=getchar(); while(c<48) c=getchar(); while(c>47) x=x*10+c-48,c=getchar(); return x; } }buf; int r=buf+1; for(int u=1;u<r;++u){ int v=buf; if(!v) t1[r].push_back(u); else do t1[v].push_back(u); while(v=buf); } sol(r); for(int i=n;i>=2;--i) f[dom[ver[i]]]+=f[ver[i]]+1; for(int u=1;u<r;++u) printf("%d\n",f[u]); }