1123: [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
Sample Output
8
8
16
14
8
题解:
其实就是个tarjan求点双。
点双并不用实际求出来,只是在搜索树中传上去,遇到割点求一下即可。
注意(x,y)和(y,x)是不同对点。
附上代码:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long
#define mmin(a,b) (a<b?a:b)
struct tree{
int u,v,next;
}l[1001000];
int n,m,lian[101000],e,ans[101000];
int dfn[101000],low[101000],num,size[101000];
void bian(int,int);
void tar(int);
signed main()
{
// freopen("in.txt","r",stdin);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%lld%lld",&x,&y);
bian(x,y);
bian(y,x);
}
tar(1);
for(int i=1;i<=n;i++) printf("%lld\n",ans[i]+2*n-2);
// while(1);
return 0;
}
void bian(int x,int y)
{
e++;
l[e].u=x;
l[e].v=y;
l[e].next=lian[x];
lian[x]=e;
}
void tar(int x)
{
dfn[x]=low[x]=++num;
size[x]=1;
int zz=0;
for(int i=lian[x];i;i=l[i].next)
{
int v=l[i].v;
if(dfn[v]==0)
{
tar(v);
size[x]+=size[v];
low[x]=mmin(low[x],low[v]);
if(dfn[x]<=low[v])
{
ans[x]+=zz*size[v]*2ll;
zz+=size[v];
}
}
else
low[x]=mmin(dfn[v],low[x]);
}
ans[x]+=zz*(n-zz-1)*2ll;
}