大致思路:
根據題目描述,能轉的起來的一定是這個有向圖的強連通分量,而且分量裏的點數大於1。
代碼:
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define IT iterator
#define PB(x) push_back(x)
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vint;
typedef vector<ll> vll;
typedef vector<ull> vull;
typedef set<int> sint;
typedef set<ull> sull;
const int maxn = 10000 + 5;
vint G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;
int a[maxn];
void init(int n) {
for (int i = 0; i <= n; i++) G[i].clear();
}
void dfs(int u) {
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (!pre[v]) {
dfs(v);
lowlink[u] = min(lowlink[u],lowlink[v]);
}
else if (!sccno[v]) {
lowlink[u] = min(lowlink[u],pre[v]);
}
}
if (lowlink[u] == pre[u]) {
scc_cnt++;
while (1) {
int x = S.top();
S.pop();
sccno[x] = scc_cnt;
if (x == u) break;
}
}
}
void find_scc(int n) {
dfs_clock = scc_cnt = 0;
CLR(sccno,0);
CLR(pre,0);
for (int i = 1; i <= n; i++) {
if (!pre[i]) dfs(i);
}
}
int cnt[maxn];
int main() {
int n,m;
//freopen("data.in","r",stdin);
while (cin>>n>>m) {
init(n);
for (int i = 0; i < m; i++) {
int a,b;
scanf("%d%d",&a,&b);
G[a].PB(b);
}
//for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
find_scc(n);
for (int i = 1; i <= n; i++) {
cnt[sccno[i]]++;
}
int ans = 0;
/*cout<<scc_cnt<<endl;
for (int i = 1; i <= scc_cnt; i++) {
for (int j = 0; j < new_g[i].size(); j++) {
cout<<i<<" "<<new_g[i][j].from<<" "<<new_g[i][j].cost<<endl;
}
}*/
for (int i = 1; i <= scc_cnt; i++) {
if (cnt[i] > 1) ans++;
}
cout<<ans<<endl;
}
}