LuoguP3469 [POI2008]BLO-Blockade

题面


分析

对每个点的贡献进行分析:如果这个点不是割点,那么去掉这个点图仍然联通,减少的访问仅为这个点和其他点之间的联系,也就是\(2*(n-1)\)。如果这个点是割点,那么去除之后图会变成多个联通块。设第\(i\)个联通块的大小为\(size_i\),易知联通块之间减少的联系是\(\Sigma_i\Sigma_j size_isize_j\)。对这个式子做变形,得到\(\Sigma_i size_i(n-size_i-1)\)。于是可以在tarjan的同时求出这个值。把所有贡献加一起就好了。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {
    
    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }
    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x=-x;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }
    
}

using namespace StandardIO;

namespace Fate {
#define int long long
	const int N=500500;
	
	int n,m;
	int cnt;
	int head[N];
	struct node {
		int to,next;
	} edge[N<<1];
	int index;
	int dfn[N],low[N],size[N],cut[N];
	int ans[N];
	
	inline void add (int a,int b) {
		edge[++cnt].to=b,edge[cnt].next=head[a],head[a]=cnt;
	}
	void tarjan (int now) {
		int tmp=0;size[now]=1,dfn[now]=low[now]=++index;
		for (register int i=head[now]; i; i=edge[i].next) {
			int to=edge[i].to;
			if (!dfn[to]) {
				tarjan(to);
				size[now]+=size[to];
				low[now]=min(low[now],low[to]);
				if (dfn[now]<=low[to]) {
					ans[now]+=tmp*size[to];
					tmp+=size[to];
				} 
			} else {
				low[now]=min(low[now],dfn[to]);
			}
		}
		ans[now]+=tmp*(n-tmp-1);
	}
    
    inline void Stay_Night () {
    	read(n),read(m);
    	for (register int i=1; i<=m; ++i) {
    		int x,y;
    		read(x),read(y);
    		add(x,y),add(y,x); 
		}
		tarjan(1);
		for (register int i=1; i<=n; ++i) {
			write((ans[i]+n-1)*2),putchar('\n');
		}
    }
#undef int  
}

int main () {
    Fate::Stay_Night();
}
posted @ 2020-07-25 14:32  Ilverene  阅读(317)  评论(0编辑  收藏  举报