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;
}