_bzoj1051 [HAOI2006]受欢迎的牛【强联通】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1051

保存tarjan模版。

求强联通分量,缩点。

#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

const int maxn = 10005, maxm = 50005;

int n, m, t1, t2;
int top[maxn], dfn[maxn], dfs_clock, scc[maxn], scc_cnt, stk[maxn], top_;
int head1[maxn], to1[maxm], next1[maxm], lb1;
int siz[maxn];
char out[maxn];

inline void ist1(int aa, int ss) {
	to1[lb1] = ss;
	next1[lb1] = head1[aa];
	head1[aa] = lb1;
	++lb1;
}
void dfs(int r) {
	dfn[r] = top[r] = ++dfs_clock;
	stk[top_++] = r;
	for (int j = head1[r]; j != -1; j = next1[j]) {
		if (!dfn[to1[j]]) {
			dfs(to1[j]);
			top[r] = std::min(top[r], top[to1[j]]);
		}
		else if (!scc[to1[j]]) {
			top[r] = std::min(top[r], dfn[to1[j]]);
		}
	}
	if (dfn[r] == top[r]) {
		++scc_cnt;
		while (stk[top_ - 1] != r) {
			scc[stk[top_ - 1]] = scc_cnt;
			--top_;
			++siz[scc_cnt];
		}
		scc[r] = scc_cnt;
		--top_;
		++siz[scc_cnt];
	}
}

int main(void) {
	//freopen("in.txt", "r", stdin);
	memset(head1, -1, sizeof head1);
	memset(next1, -1, sizeof next1);
	scanf("%d%d", &n, &m);
	while (m--) {
		scanf("%d%d", &t1, &t2);
		ist1(t1, t2);
	}
	
	for (int i = 1; i <= n; ++i) {
		if (!scc[i]) {
			dfs(i);
		}
	}
	
	for (int i = 1; i <= n; ++i) {
		for (int j = head1[i]; j != -1; j = next1[j]) {
			if (scc[i] != scc[to1[j]]) {
				out[scc[i]] = 1;
			}
		}
	}
	
	char flag = 0;
	int ans = 0;
	for (int i = 1; i <= scc_cnt; ++i) {
		if (!out[i]) {
			if (flag) {
				ans = 0;
				break;
			}
			else {
				flag = 1;
				ans = siz[i];
			}
		}
	}
	printf("%d\n", ans);
	return 0;
}

  

posted @ 2016-12-13 14:08  ciao_sora  阅读(...)  评论(... 编辑 收藏