BZOJ_P1123 [POI2008]BLO(无向图割点)

BZOJ传送门

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 810 Solved: 344
[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

Sol:
比较裸的求割点的题
在Tarjan中如果搜到的点的low[v]< deep[u]说明没法形成强连通分量就要在ans[u]中加上每两块的size的乘积
但是确定u是割点了以后,它deep比它深的连通块和deep比它浅的不连通,所以ans[u]+=c*(n-c-1)
删去后其它和u也不连通所以加上n-1再乘2

#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
#define N 100005
inline int in(int x=0,char ch=getchar()){while(ch>'9'||ch<'0') ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x;}
long long ans[N];int low[N],d[N],s[N];int n,m,cnt;
vector<int> g[N];
void Tarjan(int u,int f,long long c=0){
    low[u]=d[u]=++cnt;s[u]=1;
    for(int i=0,v,lim=g[u].size();i<lim;i++){
        if((v=g[u][i])==f) continue;
        if(!d[v]){
            Tarjan(v,u);s[u]+=s[v];low[u]=min(low[u],low[v]);
            if(low[v]>=d[u]) ans[u]+=c*s[v],c+=s[v];
        }else low[u]=min(low[u],d[v]);
    }
    ans[u]+=c*(n-1-c);ans[u]=(ans[u]+n-1)<<1;
}
int main(){
    n=in(),m=in();int u,v;
    for(int i=1;i<=m;i++){
        u=in(),v=in();
        g[u].push_back(v);g[v].push_back(u);
    }
    Tarjan(1,0);
    for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章