HDU 4694 [支配树]

来源:互联网 发布:矩阵音响 编辑:程序博客网 时间:2024/05/17 00:02

题目传送门

典型的支配树裸题,就是询问给定点到某点i的全部路径都经过的某点j。
具体讲解就不写了,网上很详细。
安利1
安利2

#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<vector>#include<algorithm>using namespace std;const int N=500001;vector<int> E[N],G[N],V[N];int son[N],dfn[N],idom[N],sdom[N],id[N],fa[N],f[N],ans[N],cnt;int find(int x){    if(f[x]==x)return x;    int y=find(f[x]);    if(sdom[son[x]]>sdom[son[f[x]]])son[x]=son[f[x]];    return  f[x]=y;}void dfs(int u){    id[dfn[u]=++cnt]=u;    for(register int v,i=0;i<E[u].size();i++)        if(v=E[u][i],!dfn[v])dfs(v),fa[dfn[v]]=dfn[u];}int n,m;inline void tarjan(int s){    for(register int i=1;i<=n;i++)f[i]=sdom[i]=son[i]=fa[i]=i,dfn[i]=0;    cnt=0,dfs(s);    register int k,x;    for(register int i=cnt;i>1;i--){        for(register int v,j=0;j<G[id[i]].size();++j)            if(v=G[id[i]][j],dfn[v])                find(k=dfn[v]),sdom[i]=sdom[i]<sdom[son[k]]?sdom[i]:sdom[son[k]];        V[sdom[i]].push_back(i),f[i]=x=fa[i];        for(register int v,j=0;j<V[f[i]].size();j++)            v=V[f[i]][j],find(k=v),idom[k]=sdom[son[k]]<x?son[k]:x;        V[x].clear();    }    for(register int i=2;i<=cnt;V[id[idom[i]]].push_back(id[i]),i++)        if(idom[i]!=sdom[i])idom[i]=idom[idom[i]];}void mp(int u,int p){    ans[u]=p;    for(register int v,i=0;i<V[u].size();++i)        v=V[u][i],mp(v,p+v);}int main(){    while(scanf("%d%d",&n,&m)!=EOF){        for(register int i=0;i<=500000;i++)G[i].clear(),V[i].clear(),E[i].clear();        for(register int u,v,i=1;i<=m;i++)scanf("%d%d",&u,&v),E[u].push_back(v),G[v].push_back(u);        tarjan(n),mp(n,n);        for(register int i=1;i<=n;i++)            printf("%d",ans[i]),putchar(i==n?'\n':' '),ans[i]=0;    }    return 0;}