hdu4694 Important Sisters 支配树

       有关支配树和Lengauer_Tarjan算法,可以见这个ppt

       注意有不能到达的点,输出0;然后就是裸的跑支配树。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define N 51005
#define inf 1000000000
using namespace std;

int n,m,tot,dfsclk,pnt[N<<3],nxt[N<<3],anc[N],bst[N],fa[N],idom[N],isem[N];
ll ans[N]; int pos[N],id[N];
int read(){
	int x=0; char ch=getchar();
	while (ch<'0' || ch>'9') ch=getchar();
	while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
	return x;
}
int les(int x,int y){
	return pos[isem[x]]<pos[isem[y]]?x:y;
}
int getanc(int x){
	if (x==anc[x]) return x;
	int t=getanc(anc[x]); bst[x]=les(bst[x],bst[anc[x]]);
	return anc[x]=t;
}
struct gragh{
	int fst[N];
	void add(int x,int y){
		pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
	}
	void clr(){ memset(fst,0,sizeof(fst)); }
}g1,g2,dom;
void dfs(int x){
	pos[x]=++dfsclk; id[dfsclk]=x; int p;
	for (p=g1.fst[x]; p; p=nxt[p]){
		int y=pnt[p];
		if (!pos[y]){ dfs(y); fa[y]=x; }
	}
}
ll solve(int x){
	if (ans[x]) return ans[x];
	if (x==n) return ans[x]=n; else return ans[x]=x+solve(idom[x]);
}
int main(){
	while (~scanf("%d%d",&n,&m)){
		int i; tot=dfsclk=0; g1.clr(); g2.clr(); dom.clr();
		for (i=1; i<=m; i++){
			int x=read(),y=read();
			g1.add(x,y); g2.add(y,x);
		}
		for (i=1; i<=n; i++) anc[i]=bst[i]=i;
		memset(idom,0,sizeof(idom)); memset(isem,0,sizeof(isem));
		memset(pos,0,sizeof(pos)); memset(id,0,sizeof(id));
		memset(fa,0,sizeof(fa));
		dfs(n); pos[0]=inf;
		for (i=dfsclk; i; i--){
			int x=id[i],p;
			if (i>1){
				for (p=g2.fst[x]; p; p=nxt[p]){
					int y=pnt[p]; if (!pos[y]) continue;
					if (pos[y]<pos[x]){
						if (pos[y]<pos[isem[x]]) isem[x]=y;
					} else{
						getanc(y); isem[x]=isem[les(x,bst[y])];
					}
				}
				dom.add(isem[x],x);
			}
			for (p=dom.fst[x]; p; p=nxt[p]){
				int y=pnt[p]; getanc(y);
				if (isem[bst[y]]!=x) idom[y]=bst[y];
					else idom[y]=x;
			}
			for (p=g1.fst[x]; p; p=nxt[p])
				if (fa[pnt[p]]==x) anc[pnt[p]]=x;
		}	
		for (i=2; i<=dfsclk; i++){
			int x=id[i];
			if (idom[x]!=isem[x]) idom[x]=idom[idom[x]];
		}
		idom[id[1]]=0;
		memset(ans,0,sizeof(ans));
		for (i=1; i<=n; i++){
			printf("%I64d",pos[i]?solve(i):0);
			putchar((i<n)?' ':'\n');
		}
	}
	return 0;
}


by lych

2016.2.26


你可能感兴趣的:(DFS,dfs序列,支配树,Lengauer_Tarjan)