cses Planets and check(tarjan) 题意 $n$个点, $m$条边, 求所有点是不是两两互相可到的, 如果不是, 就输出节点$a$和$b$, 其中$a$不能到达$b$
题解 求强连通图的板子, 使用tarjan算法, 经过一次DFS标记就可以分离scc, 并且计算scc, 基本思想是, 在DFS过程中进行标记, 并且把当前节点入栈, 对于邻接节点, 如果是没有访问过的, 就进行DFS, 如果访问过, 那么说明这个邻接节点和当前节点之间是一个环, 更新标记
如果当前节点是环的起点, 就进行出栈, 标记这个环scc
对于输出, 如果只有一个联通块, 那么就输出”YES”, 否则输出”NO” 找$a$和$b$, 由于是强连通图, 那么就找一个连通块的出度为$0$, 其中的节点可以为$b$
参考代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 #include <climits> #include <cstddef> #include <queue> #pragma GCC optimize("Ofast" ) #include <bits/stdc++.h> using namespace std;#define i128 __int128 #define DEBUG #ifdef DEBUG #define de(x) cout << (#x) << " = " << (x) << endl; #define de2(x, y) cout << (#x) << " , " << (#y) << " = " << (x) << " ~ " << (y) << endl; #else #define de(x) #define de2(x, y) #endif #define enld endl #define endl '\n' #define fi(x) for(int i = 1; i <= x; ++i) #define fi0(x) for(int i = 0; i < x; ++i) #define fj(n) for(int j = 1; j <= n; ++j) #define caillo ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define PLEASE_AC return 0 typedef long long ll;#define int long long const int N = 1e5 + 10 ;int n, m;int dfn[N], low[N], idfn, in_stack[N]; int scc[N], sz[N], sc; vector<int > adj[N]; stack<int > st; int outd[N]; void tarjan (int u) { dfn[u] = low[u] = ++idfn; in_stack[u] = 1 ; st.push (u); for (auto v : adj[u]) { if (!dfn[v]) { tarjan (v); low[u] = min (low[u], low[v]); }else if (in_stack[v]) { low[u] = min (low[u], dfn[v]); } } if (dfn[u] == low[u]) { ++sc; while (st.top () != u){ scc[st.top ()] = sc; sz[sc]++; in_stack[st.top ()] = 0 ; st.pop (); } scc[st.top ()] = sc; sz[sc]++; in_stack[st.top ()] = 0 ; st.pop (); } } void printl () { for (int i = 1 ;i <= n; ++i) { for (auto v : adj[i]) { if (scc[i] != scc[v]) outd[scc[i]]++; } } int a = 0 , b = 0 , sca = 0 ; for (int i = 1 ;i <= sc; ++i) { if (!outd[i]) { sca = i; break ; } } for (int i = 1 ;i <= n; ++i){ if (scc[i] == sca){ a = i; } if (scc[i] != sca){ b = i; } } cout << a << ' ' << b << endl; } signed main () { cin >> n >> m; fi (m) { int u, v; cin >> u >> v; adj[u].push_back (v); } for (int i = 1 ;i <= n; ++i) { if (!scc[i]) tarjan (i); } if (sc == 1 ) cout << "YES\n" ; else { cout << "NO\n" ; printl (); } }