【BZOJ-1123】BLO Tarjan 点双连通分量

1123: [POI2008]BLO

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 970  Solved: 408
[Submit][Status][Discuss]

Description

Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。

Input

输入n<=100000 m<=500000及m条边

Output

输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。

Sample Input

5 5
1 2
2 3
1 3
3 4
4 5

Sample Output

8
8
16
14
8

HINT

Source

Solution

题意叙述不清。

题目大意:给定N个点M条边的无向图,问删除每个点后,对于有序数对(x,y)满足x,y互不连通的数对数。其中,被删掉的点也应被统计。

这种和删点,联通有关的,可以考虑割点/点双联通分量。

这个题也是,如果删除一个割点,那么答案个数就是裂成的几个块用乘法原理统计答案。如果删除一个非割点则可能会对其他点直接不影响。

可以考虑在Tarjan的过程中求解,我们额外记录一个size表示分成的联通块的大小,然后我们在Tarjan的过程中统计答案即可

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
#define LL long long
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;
}
#define MAXN 100010
#define MAXM 500010
struct EdgeNode{int next,to;}edge[MAXM<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int N,M;
vector<int>BCC[MAXN];
#define Pa pair<int,int>
Pa st[MAXM]; int top;
int dfn[MAXN],low[MAXN],dfsn,son[MAXN],size[MAXN],cut[MAXN],bcc,belong[MAXN];
LL sum[MAXN];
inline void Tarjan(int now,int last)
{
    dfn[now]=low[now]=++dfsn;  LL su=0; size[now]=1;
    for (int i=head[now]; i; i=edge[i].next)
        if (!dfn[edge[i].to])
            {
                st[++top]=make_pair(now,edge[i].to); son[now]++;
                Tarjan(edge[i].to,now); low[now]=min(low[now],low[edge[i].to]);
                size[now]+=size[edge[i].to];
                if (dfn[now]<=low[edge[i].to])
                    {
                        sum[now]+=su*size[edge[i].to]; su+=(LL)size[edge[i].to];
                        cut[now]=1; bcc++; BCC[bcc].clear(); int tnow=-1,tto=-1;
                        while (tnow!=now && tto!=edge[i].to)
                            {
                                tnow=st[top].first,tto=st[top].second; top--;
                                if (belong[tnow]!=bcc) BCC[bcc].push_back(tnow),belong[tnow]=bcc;
                                if (belong[tto]!=bcc) BCC[bcc].push_back(tto),belong[tto]=bcc;
                            }
                    }
            }
        else if (dfn[edge[i].to]<dfn[now] && edge[i].to!=last)
            st[++top]=make_pair(now,edge[i].to),low[now]=min(low[now],dfn[edge[i].to]);
    if (last<0 && son[now]==1) cut[now]=0;
    sum[now]+=su*(N-su-1);
}
int main()
{
    N=read(),M=read();
    for (int x,y,i=1; i<=M; i++) x=read(),y=read(),InsertEdge(x,y);
    for (int i=1; i<=N; i++) if (!dfn[i]) Tarjan(i,-1);
    for (int i=1; i<=N; i++) printf("%lld\n",(LL)(sum[i]+N-1)*2);
    return 0;
}

 

posted @ 2016-09-25 08:17  DaD3zZ  阅读(1537)  评论(0编辑  收藏  举报