洛谷P2002 消息扩散(tarjan缩点)

题目链接: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 }

 

 
posted @ 2022-09-06 16:12  Keyzee  阅读(6)  评论(0编辑  收藏  举报