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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章