1. 程式人生 > >BZOJ1123: [POI2008]BLO(洛谷P3469)

BZOJ1123: [POI2008]BLO(洛谷P3469)

Tarjan

顯然不是割點的點答案都是(n1)2(n-1)*2,我們只需要算一算割點的答案就好了。而割點的額外答案為DFS樹上各個子樹之間兩兩配對的貢獻加上子樹內和子樹外的貢獻。這些在Tarjan求割點的同時都可以順帶出來。

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 500005
#define F inline
using namespace std;
typedef long long
LL; struct edge{ int nxt,to; }ed[M<<2]; int n,m,k,ti,h[N],dfn[N],low[N],sz[N]; LL ans[N]; F char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); return l==r?EOF:*l++; } F int _read(){ int x=0; char ch=readc(); while (!isdigit(ch)) ch=readc(); while (isdigit
(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc(); return x; } void Tarjan(int x){ dfn[x]=low[x]=++ti,sz[x]=1; LL t=0; for (int i=h[x],v;i;i=ed[i].nxt) if (!dfn[v=ed[i].to]){ Tarjan(v),sz[x]+=sz[v],low[x]=min(low[x],low[v]); if (low[v]>=dfn[x]) ans[x]+=t*sz[v],t+=sz[v]; } else low[
x]=min(low[x],dfn[v]); (ans[x]+=t*(n-t-1)+n-1)<<=1; } #define add(x,y) ed[++k]=(edge){h[x],y},h[x]=k int main(){ n=_read(),m=_read(),k=1; for (int i=1,x,y;i<=m;i++) x=_read(),y=_read(),add(x,y),add(y,x); Tarjan(1); for (int i=1;i<=n;i++) printf("%lld\n",ans[i]); return 0; }