bzoj1123(权限题)

版权声明: https://blog.csdn.net/Richard_for_OI/article/details/79477267

割点的题目,一定要考虑全面。注意有序点对,必须×2。

因为删掉割点的所有边后,可能形成的连通块有:

1、孤单的节点i自己  2、i的儿子的子树们 3、除了这些点,剩下的所有点构成一个

//权限题 
#include <cstdio>
#define N 100010
#define M 500010
#include <algorithm>
using namespace std;
typedef long long ll;
struct adj {int to, next;}e[2*M];
int head[N], n, m, cnt = 1, num = 0, Size[N], dfn[N], low[N];
ll ans[N];
inline int read() {
	int x = 0; char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = getchar();}
	return x;
}
inline void ins(int x, int y) {e[++cnt].to = y; e[cnt].next = head[x]; head[x] = cnt;}
inline void tarjan(int x) {
	int t = 0; Size[x] = 1;
	dfn[x] = low[x] = ++num;
	for(int i = head[x]; i; i = e[i].next) {
		int y = e[i].to;
		if(!dfn[y]) {
			tarjan(y);
			Size[x]+= Size[y];
			low[x] = min(low[x], low[y]);
			if(dfn[x] <= low[y]) {
				ans[x]+= (ll)t * Size[e[i].to];
				t+= Size[y];
			}
		}else low[x] = min(low[x], dfn[y]);
	}
	ans[x]+= (ll)t * (n - t - 1);
}
int main() {
	n = read(); m = read();
	for(int i = 1; i <= m; ++i) {int x = read(), y = read(); ins(x, y); ins(y, x);}
	tarjan(1);
	for(int i = 1; i <= n; ++i) printf("%lld\n", (ans[i] + n - 1) * 2);
	return 0;
}

展开阅读全文

没有更多推荐了,返回首页