题目链接:https://www.luogu.com.cn/problem/P2002
思路:由于图中每个强连通分量(scc)中的点是可以互相到达的,所以我们可以用tarjan求图中scc,然后将所有scc缩点,最后求缩点之后图中入度为0的点的个数就是答案。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<map> 5 #include<queue> 6 #include<set> 7 #include<algorithm> 8 #include<stack> 9 #include<cmath> 10 #include<cstring> 11 #include<string> 12 using namespace std; 13 #define gc getchar() 14 #define rd(x) read(x) 15 #define el '\n' 16 #define rep(i, a, n) for(int i = (a); i <= n; ++i) 17 #define per(i, a, n) for(int i = (a); i >= n; --i) 18 using ll = long long; 19 using db = double; 20 using ldb = long double; 21 const int mod = 1e9 + 7; 22 const int inf = 0x3f3f3f3f; 23 const int N = 100000 + 10; 24 25 template <typename _T> 26 inline void read(_T& f) { 27 f = 0; _T fu = 1; char c = gc; 28 while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = gc; } 29 while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = gc; } 30 f *= fu; 31 } 32 33 template <typename T> 34 void print(T x) { 35 if (x < 0) putchar('-'), x = -x; 36 if (x < 10) putchar(x + 48); 37 else print(x / 10), putchar(x % 10 + 48); 38 } 39 40 template <typename T> 41 void print(T x, char t) { 42 print(x); putchar(t); 43 } 44 45 int dfn[N], low[N], ins[N], scc[N], in[N]; 46 int dfncnt, scccnt; 47 stack<int>st; 48 vector<int>G[N]; 49 vector<int>DAG[N]; 50 51 int n, m; 52 int pmax; 53 54 void tarjan(int u) { 55 dfn[u] = ++dfncnt; 56 low[u] = dfncnt; 57 st.push(u); 58 ins[u] = true; 59 for (int i = 0; i < G[u].size(); i++) { 60 int v = G[u][i]; 61 if (!dfn[v]) { 62 tarjan(v); 63 low[u] = min(low[u], low[v]); 64 } 65 else if (ins[v]) { 66 low[u] = min(low[u], dfn[v]); 67 } 68 } 69 if (dfn[u] == low[u]) { 70 int v; 71 ++scccnt; 72 pmax = max(pmax, scccnt); 73 do { 74 v = st.top(); 75 st.pop(); 76 ins[v] = false; 77 scc[v] = scccnt; 78 } while (u != v); 79 } 80 } 81 82 void getdag() { 83 for (int i = 1; i <= n; i++) { 84 if (!dfn[i]) { 85 tarjan(i); 86 } 87 } 88 for (int u = 1; u <= n; u++) { 89 for (int j = 0; j < G[u].size(); j++) { 90 int v = G[u][j]; 91 if (scc[u] != scc[v]) { 92 DAG[scc[u]].push_back(scc[v]); 93 in[scc[v]]++; 94 } 95 } 96 } 97 } 98 99 int main() { 100 101 ios::sync_with_stdio(false); 102 cin.tie(0), cout.tie(0); 103 //int n, m; 104 cin >> n >> m; 105 for (int i = 1; i <= m; i++) { 106 int u, v; 107 cin >> u >> v; 108 G[u].push_back(v); 109 } 110 getdag(); 111 int ans = 0; 112 for (int i = 1; i <= pmax; i++) { 113 if (!in[i]) ans++; 114 } 115 cout << ans << el; 116 117 return 0; 118 }
标签:缩点,P2002,tarjan,int,void,scc,low,include From: https://www.cnblogs.com/wabi/p/16662221.html