1.题面
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; }