BZOJ1123:[POI2008]BLO(双连通分量)
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
1 2
2 3
1 3
3 4
4 5
Sample Output
8
8
16
14
8
8
16
14
8
Solution
题意不清楚。点对(x,y)!=(y,x),且去掉的点也要考虑进答案
当我们dfs找割点的时候,会形成一颗dfs树
对于一个割点x,若将其去掉,可以分成x上面的一颗子树和x的若干子树
Tarjan的时候乘法原理统计一下答案即可
当我们dfs找割点的时候,会形成一颗dfs树
对于一个割点x,若将其去掉,可以分成x上面的一颗子树和x的若干子树
Tarjan的时候乘法原理统计一下答案即可
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (100000+1000) 5 #define M (500000+1000) 6 using namespace std; 7 8 struct Edge{int from,to,next;}edge[M<<1]; 9 int n,m,u,v,head[N],num_edge; 10 int Dfn[N],Low[N],dfs_num,Cut[N]; 11 long long size[N],ans[N]; 12 13 void add(int u,int v) 14 { 15 edge[++num_edge].from=u; 16 edge[num_edge].to=v; 17 edge[num_edge].next=head[u]; 18 head[u]=num_edge; 19 } 20 21 void Tarjan(int x,int fa) 22 { 23 long long son_num=0,sum=0; 24 size[x]=1; 25 Dfn[x]=Low[x]=++dfs_num; 26 for (int i=head[x]; i; i=edge[i].next) 27 if (!Dfn[edge[i].to]) 28 { 29 son_num++; 30 Tarjan(edge[i].to,x); 31 size[x]+=size[edge[i].to]; 32 Low[x]=min(Low[x],Low[edge[i].to]); 33 if (Low[edge[i].to]>=Dfn[x]) 34 { 35 Cut[x]=true; 36 ans[x]+=sum*size[edge[i].to]; 37 sum+=size[edge[i].to]; 38 } 39 } 40 else 41 if (Dfn[x]>Dfn[edge[i].to] && edge[i].to!=fa) 42 Low[x]=min(Low[x],Dfn[edge[i].to]); 43 if (fa==0 && son_num==1) 44 Cut[x]=false; 45 if (Cut[x]) ans[x]+=sum*(n-sum-1); 46 } 47 48 int main() 49 { 50 scanf("%d%d",&n,&m); 51 for (int i=1; i<=m; ++i) 52 { 53 scanf("%d%d",&u,&v); 54 add(u,v); add(v,u); 55 } 56 for (int i=1; i<=n; ++i) 57 if (!Dfn[i]) 58 Tarjan(i,0); 59 for (int i=1; i<=n; ++i) 60 printf("%lld\n",(long long)(ans[i]+n-1)*2); 61 }