Description
给定一张无向图,求每个点被*(删去与其相连的边)之后有多少个有序点对(x,y)(x!=y,1<=x,y<=n)满足x无法到达y.
Input&Output
Input
第一行两个整数n,m. 分别为点数和边数。
接下来m行,每行两个整数a,b,代表a和b之间有一条边。
Output
共n行,每行一个整数,即*每个点后的答案。
Sample
Input
5 5
1 2
2 3
1 3
3 4
4 5
Output
8
8
16
14
8
Solution
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 100005
#define maxm 500005
using namespace std;
typedef long long ll;
struct edge{
int to,nxt;
}e[maxm<<1];
int n,m,edgenum,lnk[maxn],low[maxn],dfn[maxn],vis[maxn],cut[maxn];
int cnt,size[maxn],root,a,b;
ll ans[maxn],sum;
void add(int bgn,int end)
{
e[++edgenum].to=end;
e[edgenum].nxt=lnk[bgn];
lnk[bgn]=edgenum;
}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
size[x]=1;
int children=0,sum=0;
for(int p=lnk[x];p;p=e[p].nxt){
int y=e[p].to;
if(!dfn[y]){
tarjan(y);
size[x]+=size[y];
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
children++;
ans[x]+=(long long)size[y]*(n-size[y]);
sum+=size[y];
if(x!=root||children>1)cut[x]=1;
}
}
else low[x]=min(low[x],dfn[y]);
}
if(cut[x]) ans[x]+=(long long)(n-1-sum)*(1+sum)+(n-1);
else ans[x]=2*(n-1);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
scanf("%d%d",&a,&b),add(a,b),add(b,a);
root=1;
tarjan(1);
for(int i=1;i<=n;++i)
printf("%lld\n",ans[i]);
return 0;
}