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
solution
首先,我们要看懂样例,
我们可以用n*(n-1)减去剩下的点对,也可以直接算。
注意一对点对可以正反两次连接,算两个点对。
如果,样例看懂了,这道题就easy了,
有tarjan求一下割点,在求割点的过程中,
记录消失的点对就ok了
#include
#include
#include
#include
#include
#include
using namespace std; int k,m,n,x,y,tp=0,tim=0,num=0; int hea[1200010],nex[4000010],tail[4000010]; int dfn[1100010],low[1100010],pd[1100010],sz1[1100010]; long long ans[1100010]; void add(int x,int y) { nex[++tp]=hea[x]; hea[x]=tp; tail[tp]=y; } void dfs(int a,int fa) { sz1[a]=1; dfn[a]=low[a]=++tim; int sz=0; for (int i=hea[a];i!=-1;i=nex[i]) { int b=tail[i]; if (!dfn[b]) { dfs(b,a); sz1[a]+=sz1[b];low[a]=min(low[a],low[b]); if (low[b]>=dfn[a]&&a!=fa) { ans[a]+=(long long)sz*sz1[b]; sz+=sz1[b]; } } else low[a]=min(low[a],dfn[b]); } ans[a]+=n-1; ans[a]+=(long long)sz*(n-sz-1); } int main() { memset(hea,-1,sizeof(hea)); scanf ("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf ("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0); for (int i=1;i<=n;i++) printf ("%lld\n",ans[i]*2); return 0; }