[hdu4694]Important Sisters

来自FallDream的博客,未经允许,请勿转载,谢谢。


 

给定一张图,求每个点到第n个点必须经过的点的编号之和。n<=50000

 

一道支配树裸题

然后统计答案的时候可以正着推,ans[i]=ans[idom[i]]+i

#include<iostream>
#include<cstdio>
#include<cstring>
#define MN 50000
#define ll long long
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
ll val[MN+5];
int n,m,cnt,tot=0,mark[MN+5],dn,head[MN+5],Fa[MN+5],fa[MN+5],top[MN+5],back[MN+5],Best[MN+5],dfn[MN+5],id[MN+5],s[MN+5],d[MN+5];
struct edge{int to,next;}e[MN*100];
inline void ins(int*H,int f,int t){e[++cnt]=(edge){t,H[f]};H[f]=cnt;}

void Pre(int x)
{
    id[dfn[x]=++dn]=x;
    for(int    i=head[x];i;i=e[i].next)
        if(!dfn[e[i].to]) Fa[e[i].to]=x,Pre(e[i].to);
}
inline bool P(int x,int y){return dfn[x]>dfn[y];}
inline int Up(int x)
{
    if(fa[x]==x) return x;
    int y=Up(fa[x]);
    if(P(s[Best[x]],s[Best[fa[x]]])) Best[x]=Best[fa[x]];
    return fa[x]=y;
}

inline void Tarjan()
{
    for(int i=dn;i>1;--i)
    {
        int u=id[i];
        for(int j=back[u];j;j=e[j].next)
            if(dfn[e[j].to])
                Up(e[j].to),P(s[u],s[Best[e[j].to]])?s[u]=s[Best[e[j].to]]:0;
        ins(top,s[u],u);fa[u]=Fa[u];u=Fa[u];
        for(int j=top[u];j;j=e[j].next)
        {
            Up(e[j].to);
            if(s[Best[e[j].to]]==s[u]) d[e[j].to]=u;
            else d[e[j].to]=Best[e[j].to];
        }
    }
    for(int i=2;i<=dn;++i) if(d[id[i]]!=s[id[i]]) d[id[i]]=d[d[id[i]]];
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        cnt=dn=0;++tot;
        memset(head,0,sizeof(int)*(n+2));
        memset(back,0,sizeof(int)*(n+2));
        memset(top,0,sizeof(int)*(n+2));
        memset(val,0,sizeof(ll)*(n+2));
        memset(dfn,0,sizeof(int)*(n+2));
        memset(d,0,sizeof(int)*(n+2));
        for(int i=1;i<=m;++i)
        {
            int u=read(),v=read();
            ins(head,u,v);
            ins(back,v,u);    
        }
        for(int i=1;i<=n;++i) Best[i]=s[i]=fa[i]=i;    
        Pre(n);Tarjan();
        for(int i=1;i<=dn;++i) val[id[i]]=val[d[id[i]]]+id[i];
        for(int i=1;i<=n;++i) printf("%I64d%c",dfn[i]?val[i]:0,i==n?'\n':' ');
    }
    return 0;
}

 

posted @ 2017-05-19 19:00  FallDream  阅读(345)  评论(0编辑  收藏  举报