zoukankan      html  css  js  c++  java
  • HDU.4694.Important Sisters(支配树)

    HDU

    (Description)

    给定一张简单有向图,起点为(n)。对每个点求其支配点的编号和。
    (nleq 50000)

    (Solution)

    支配树。

    还是有点小懵逼。
    不管了,说不定会讲,反正以后再说。

    https://blog.csdn.net/litble/article/details/83019578
    有图的:https://blog.csdn.net/VioletSu/article/details/81041954
    有题的:https://blog.csdn.net/L_0_Forever_LF/article/details/79386508
    有怎么卡纯路径压缩并查集的:https://www.cnblogs.com/meowww/archive/2017/02/27/6475952.html

    记几个名词:
    (Lengauer Tarjan)算法。
    半支配点((semi-dominator)),记作(semi(x))
    最近支配点((immediate dominator)),记作(idom(x))


    想不到我竟然也有把if(x==y)写成if(x=y)而且还调半天的时候...

    //1107MS	8292K
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=50005,M=1e5+5;
    
    int Index,dfn[N],ref[N],F[N],fa[N],mn[N],semi[N],idom[N],Ans[N];
    struct Graph
    {
    	int Enum,H[N],nxt[M],to[M];
    	inline void Clear(int n)
    	{
    		Enum=0, memset(H,0,n+1<<2);
    	}
    	inline void AE(int u,int v)
    	{
    		to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	}
    }G,RG,SG,T;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    void DFS0(int x)
    {
    	ref[dfn[x]=++Index]=x;
    	for(int i=G.H[x],v; i; i=G.nxt[i])
    		if(!dfn[v=G.to[i]]) fa[v]=x, DFS0(v);
    }
    int Find(int x)
    {
    	if(x==F[x]) return x;
    	int tmp=F[x];
    	F[x]=Find(F[x]);
    	if(dfn[semi[mn[tmp]]]<dfn[semi[mn[x]]]) mn[x]=mn[tmp];
    	return F[x];
    }
    void DFS(int x,int s)
    {
    	Ans[x]=s+=x;
    	for(int i=T.H[x]; i; i=T.nxt[i]) DFS(T.to[i],s);
    }
    void Solve(int n)
    {
    	for(int k=n; k>1; --k)
    	{
    		int x=ref[k],t=n;//求半支配点 
    		for(int i=RG.H[x],v; i; i=RG.nxt[i])
    			if(dfn[v=RG.to[i]])
    				if(dfn[v]<dfn[x]) t=std::min(t,dfn[v]);
    				else Find(v), t=std::min(t,dfn[semi[mn[v]]]);
    		F[x]=fa[x], SG.AE(semi[x]=ref[t],x);
    
    		x=ref[k-1];//从半支配点到支配点 
    		for(int i=SG.H[x],v; i; i=SG.nxt[i])
    		{
    			Find(v=SG.to[i]);
    			if(semi[v]==semi[mn[v]]) idom[v]=semi[v];
    			else idom[v]=mn[v];//idom[mn[v]]此时可能并未找到 
    		}
    	}
    	for(int k=2,x; k<=n; ++k)
    	{
    		x=ref[k];
    		if(idom[x]!=semi[x]) idom[x]=idom[idom[x]];
    		T.AE(idom[x],x);
    	}
    	DFS(n,0);
    	for(int i=1; i<n; printf("%d ",Ans[i++]));
    	printf("%d
    ",Ans[n]), memset(Ans,0,n+1<<2);
    }
    
    int main()
    {
    	int n,m;
    	while(~scanf("%d%d",&n,&m))
    	{
    		for(int i=1,u,v; i<=m; ++i) u=read(),v=read(),G.AE(u,v),RG.AE(v,u);
    		for(int i=1; i<=n; ++i) F[i]=semi[i]=mn[i]=i;
    		Index=0, DFS0(n), Solve(n);
    		G.Clear(n), RG.Clear(n), SG.Clear(n), T.Clear(n);
    		memset(dfn,0,n+1<<2), memset(idom,0,n+1<<2), memset(ref,0,n+1<<2);//, memset(fa,0,n+1<<2);//不都清空会RE啊== 
    	}
    	return 0;
    }
    
  • 相关阅读:
    python的metaclass
    鱼和水的故事
    iOS的QuickTime Plugin
    二进制/十六进制转浮点数的编程(互转类似)
    Android开发常见错误及技巧
    Mac 热键大全
    Java动态程序设计:反射介绍
    注册asp.net 4.0 到iis
    javascript常用判断写法
    将存储过程执行的结果保存到临时表
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10123414.html
Copyright © 2011-2022 走看看