POI2008BLO-Blockade 割点
Solution:
直接分情况讨论一下:
<1>、若去掉的点不是割点:
则贡献为: 2*(n-1)。
<2>、 若去掉的是割点:
图被分为若干连通块。且对于每个连通块内的点都与其他连通块内的点,构成贡献。
若记每个连通块的大小为S1,S2,S3...SN,那么:
贡献为:
1*(n-1)+(n-1-∑S[1..N])*(∑S[1..N]+1);
Code↓:
#include<string>
#include<cstdio>
#include<cstring>
#define RG register
#define IL inline
#define LL long long
#define DB double
using namespace std;
IL int gi() {
char ch=getchar(); RG int x=0,w=0;
while (ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
return w?-x:x;
}
const int N=1e5+10;
const int M=1e6+10;
LL ans[N];
int n,m,Time,tot,head[N],dfn[N],low[N],size[N],tag[N];
struct EDGE{int next,to;}e[M];
IL void make(int x,int y) {
e[++tot]=(EDGE){head[x],y},head[x]=tot;
e[++tot]=(EDGE){head[y],x},head[y]=tot;
}
void Tarjan(int x) {
RG int i,y,sum=0,cnt=0;
dfn[x]=low[x]=++Time,size[x]=1;
for (i=head[x];i;i=e[i].next) {
y=e[i].to;
if (!dfn[y]) {
Tarjan(y),size[x]+=size[y];
low[x]=min(low[x],low[y]);
if (low[y]>=dfn[x]) {
sum+=size[y];
ans[x]+=1ll*size[y]*(n-size[y]);
if (x!=1||++cnt>1) tag[x]=1;
}
}
else low[x]=min(low[x],dfn[y]);
}
if (tag[x]) ans[x]+=1ll*(sum+1)*(n-sum-1)+(n-1);
else ans[x]=2*(n-1);
}
int main()
{
RG int i,x,y;
n=gi(),m=gi();
for (i=1;i<=m;++i) x=gi(),y=gi(),make(x,y);
Tarjan(1);
for (i=1;i<=n;++i) printf("%lld\n",ans[i]);
return 0;
}