uva 1108 - Mining Your Own Business(强连通)

题目链接:uva 1108 - Mining Your Own Business


一个联通分量里面如果只有一个割点,则说明该联通分量里面需要一个天井,并且不能建在割点上。特殊情况下为只有一个联通分量的情况,需要选两个点。


#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>

using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn = 1e5 + 5;

int N, T[maxn], L[maxn], R[maxn];
int cntlock, cntbcc, pre[maxn], low[maxn], bccno[maxn], iscut[maxn];
vector<int> G[maxn], BCC[maxn];
stack<pii> S;

int dfs (int u, int fa) {
	int lowu = pre[u] = ++cntlock, child = 0;

	for (int i = 0; i < G[u].size(); i++) {
		int v = G[u][i];
		pii e = make_pair(u, v);

		if (!pre[v]) {
			child++;
			S.push(e);
			int lowv = dfs(v, u);
			lowu = min(lowu, lowv);

			if (lowv >= pre[u]) {
				iscut[u] = 1;
				BCC[++cntbcc].clear();

				while (true) {
					e = S.top(); S.pop();
					if (bccno[e.first] != cntbcc) {
						BCC[cntbcc].push_back(e.first);
						bccno[e.first] = cntbcc;
					}
					if (bccno[e.second] != cntbcc) {
						BCC[cntbcc].push_back(e.second);
						bccno[e.second] = cntbcc;
					}

					if (u == e.first && v == e.second) break;
				}
			}
		} else if (v != fa && pre[v] < pre[u]) {
			S.push(e);
			lowu = min(lowu, pre[v]);
		}
	}

	if (fa < 0 && child == 1) iscut[u] = 0;
	return low[u] = lowu;
}

void findBCC () {
	cntlock = cntbcc = 0;
	memset(pre, 0, sizeof(pre));
	memset(iscut, 0, sizeof(iscut));
	memset(bccno, 0, sizeof(bccno));
	dfs(0, -1);
}

void init () {
	int n = 0;
	for (int i = 1; i <= N; i++) {
		scanf("%d%d", &L[i], &R[i]);
		T[n++] = L[i];
		T[n++] = R[i];
	}

	sort(T, T + n);
	n = unique(T, T + n) - T;

	for (int i = 0; i < n; i++) G[i].clear();

	for (int i = 1; i <= N; i++) {
		int u = lower_bound(T, T + n, L[i]) - T;
		int v = lower_bound(T, T + n, R[i]) - T;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	N = n;
	findBCC();
}

int main () {
	int cas = 1;
	while (scanf("%d", &N) == 1 && N) {
		init ();
		ll ans1 = 0, ans2 = 1;

		if (cntbcc == 1) {
			ans1 = 2, ans2 = 1LL * N * (N-1) / 2;
		} else {
			for (int i = 1; i <= cntbcc; i++) {
				int c = 0;
				for (int j = 0; j < BCC[i].size(); j++)
					if (iscut[BCC[i][j]]) c++;
				if (c == 1) {
					ans1++;
					ans2 *= BCC[i].size() - c;
				}
			}
		}
		printf("Case %d: %lld %lld\n", cas++, ans1, ans2);
	}
	return 0;
}


你可能感兴趣的:(uva 1108 - Mining Your Own Business(强连通))