1.题面
2.题意
给出若干个定理之间的证明关系,问你至少还需要几个证明,可以使得所有命题等价
3.思路
采用强连通分量缩点,随后找入度为0和出度为0的类型的点中较多的那个,当整个图为一个强连通分量的时候,答案为0
4.代码
/*****************************************************************
> File Name: acm.cpp
> Author: Uncle_Sugar
> Mail: uncle_sugar@qq.com
> 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;
}