BZOJ-1123: [POI2008]BLO

[文章目录]

Description

Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。 n<=10^5 m<=5*10^5

tarjan求点双,建出圆方树后DP计数即可。

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 101000 
#define M 1001000 
typedef long long ll;
inline char nc()
{
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    int re=0; char ch=nc();
    while(!isdigit(ch)) ch=nc();
    while(isdigit(ch)) re=re*10+(ch^'0'),ch=nc();
    return re;
}
int n,m,tot,head[N],to[M],nxt[M],cnt;
inline void add(int x,int y)
{
    to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt;
    to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt;
}
int Head[N<<1],To[N<<2],Nxt[N<<2],Cnt;
inline void Add(int x,int y)
{
    To[++Cnt]=y; Nxt[Cnt]=Head[x]; Head[x]=Cnt;
    To[++Cnt]=x; Nxt[Cnt]=Head[y]; Head[y]=Cnt;
}
int z[N],top,dfn[N],low[N],tim;
void tarjan(int x,int pre)
{
    z[++top]=x; dfn[x]=low[x]=++tim; int y;
    for(int i=head[x];i;i=nxt[i]) if(to[i]!=pre)
    {
        if(!dfn[y=to[i]])
        {
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x])
            {
                int t; tot++;
                do
                {
                    t=z[top--];
                    Add(tot,t);
                }while(t!=y);
                Add(tot,x);
            }
        }
        else low[x]=min(low[x],dfn[y]);
    }
}
int siz[N<<1];
ll ans[N<<1];
void dfs(int x,int pre)
{
    ll t=0; siz[x]=(x<=n);
    for(int i=Head[x];i;i=Nxt[i]) if(To[i]!=pre)
    {
        dfs(To[i],x);
        ans[x]+=t*siz[To[i]];
        siz[x]+=siz[To[i]];
        t+=siz[To[i]];
    }
    ans[x]+=t*(n-siz[x]);
}
int main()
{
    tot=n=read(); m=read();
    while(m--) add(read(),read());
    tarjan(1,0);
    dfs(1,0);
    for(int i=1;i<=n;++i) printf("%lld\n",(ans[i]+(n-1))*2);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注