UVALive - 4287 Proving Equivalences

1.题面

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2288

2.题意

给出若干个定理之间的证明关系,问你至少还需要几个证明,可以使得所有命题等价

3.思路

采用强连通分量缩点,随后找入度为0和出度为0的类型的点中较多的那个,当整个图为一个强连通分量的时候,答案为0

4.代码

/*****************************************************************
    > File Name: acm.cpp
    > Author: Uncle_Sugar
    > Mail: [email protected]
    > Created Time: 2016/11/5 20:44:01
*****************************************************************/
# include <cstdio>
# include <cstring>
# include <cctype>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <iostream>
# include <iomanip>
# include <set>
# include <map>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
using namespace std;

const int size  = 5000 + 10; 
const int INF = INT_MAX>>1;
typedef long long ll;


/*
Tarjan 算法模板,注意scc的编号从1开始
*/

const int MAXN = 20000 + 1000;
const int MAXM = 50000 + 1000;

int head[MAXN];
struct Edge{
	int to, nxt;
}edge[MAXM];
int tot;

void init(){
	tot = 0;
	memset(head, -1, sizeof(head));
}

void addedge(int from, int to){
	edge[tot].to = to; edge[tot].nxt = head[from]; head[from] = tot++;
}

int pre[MAXN], lowlink[MAXN], sccno[MAXN], dfs_clock, scc_cnt;
int stk[MAXN], top;

int n, m;

void dfs(int u){
	pre[u] = lowlink[u] = ++dfs_clock;
	/*这里不能改成dfs_clock++, 因为pre[v] == 0是v未被访问的标志*/
	stk[top++] = u;
	
	for (int e = head[u]; ~e; e = edge[e].nxt){
		int v = edge[e].to;
		if (!pre[v]){
			dfs(v);
			lowlink[u] = min(lowlink[u], lowlink[v]);
		}else if (!sccno[v]){
			lowlink[u] = min(lowlink[u], pre[v]);
		}
	}

	if (pre[u] == lowlink[u]){
		scc_cnt++;
		for (;;){
			int x = stk[--top];
			sccno[x] = scc_cnt;
			if (x == u) break;
		}
	}
}

void find_scc(int n){
	scc_cnt = dfs_clock = top = 0;
	memset(lowlink, 0, sizeof(lowlink));
	memset(pre, 0, sizeof(pre));
	memset(sccno, 0, sizeof(sccno));
	for (int i = 0; i < n; i++)
		if (!pre[i]) dfs(i);
}

int in[MAXN], out[MAXN];

int main(){
	int T;
	scanf("%d", &T);
	while (T--){
		init();
		scanf("%d%d", &n, &m);
		while (m--){
			int a, b;
			scanf("%d%d", &a, &b);a--;b--;
			addedge(a, b);
		}
		
		find_scc(n);
		
		for (int i = 1; i <= scc_cnt; i++) in[i] = out[i] = 1;
		
		for (int i = 0; i < n; i++)
			for (int e = head[i]; ~e; e = edge[e].nxt){
				int v = edge[e].to;
				if (sccno[i] != sccno[v]){
					out[sccno[i]] = in[sccno[v]] = 0;
				}
			}
		int a = 0, b = 0;
		for (int i = 1; i <= scc_cnt; i++){
			if (in[i])  a++;
			if (out[i]) b++;
		}
		
		int ans = max(a, b);
		if (scc_cnt == 1) ans = 0;
		printf("%d\n", ans);

	}
	return 0;
}








猜你喜欢

转载自blog.csdn.net/sinat_29278271/article/details/53053351