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]);
}
posted @ 2016-05-15 21:44  f321dd  阅读(312)  评论(0编辑  收藏  举报