Description
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
输入n<=100000 m<=500000及m条边
Solution
若图是点双连通的,那么无论删掉哪个点都不影响答案
考虑建出圆方树,我们统计的实际上是经过点x的路径数量,这个统计一下树上的size然后就可以算答案了
注意答案是双向的。。要乘2开LL
Solution
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int N=200005;
const int E=1000005;
struct Graph {
struct edge {int y,next;} e[E];
int ls[N],edCnt;
void add_edge(int x,int y) {
e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
}
} G,T;
std:: stack <int> stack;
int dfn[N],low[N],tot,n;
LL ans[N],size[N];
bool vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void dfs1(int now,int from) {
dfn[now]=low[now]=++dfn[0];
vis[now]=true;
for (int i=G.ls[now];i;i=G.e[i].next) {
if ((i^1)==from) continue;
if (!dfn[G.e[i].y]) {
stack.push(i); dfs1(G.e[i].y,i);
low[now]=std:: min(low[now],low[G.e[i].y]);
if (dfn[now]<=low[G.e[i].y]) {
int y=0; tot++;
while (y!=i) {
y=stack.top(); stack.pop();
T.add_edge(G.e[y].y,tot);
// printf("%d %d\n", tot,G.e[y].y);
}
T.add_edge(now,tot);
// printf("%d %d\n", now,tot);
}
} else if (vis[G.e[i].y]) low[now]=std:: min(dfn[G.e[i].y],low[now]);
}
vis[now]=false;
}
void dfs2(int now,int fa) {
size[now]=(now<=n);
for (int i=T.ls[now];i;i=T.e[i].next) {
if (T.e[i].y==fa) continue;
dfs2(T.e[i].y,now);
ans[now]+=size[now]*size[T.e[i].y];
size[now]+=size[T.e[i].y];
}
ans[now]+=(size[now])*(n-size[now]);
}
int main(void) {
T.edCnt=G.edCnt=1;
n=tot=read(); int m=read();
rep(i,1,m) G.add_edge(read(),read());
dfs1(1,0);
dfs2(1,0);
rep(i,1,n) printf("%lld\n", ans[i]*2LL);
return 0;
}