[Luogu] 校园网Network of Schools
https://www.luogu.org/problemnew/show/2746
Tarjan 缩点
判断入度为0的点的个数与出度为0的点的个数的关系
注意全缩为一个点的情况
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int N = 110; #define yxy getchar() int n, now = 1, Tarjan_tim, Bel_tim, Top; int head[N], Low[N], Dfn[N], Out[N], In[N], Belong[N], Stack[N]; bool vis[N]; struct Node {int u, v, nxt;} G[N * N * 2]; inline int read(){ int x = 0; char c = yxy; while(c < '0' || c > '9') c = yxy; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = yxy; return x; } inline void add(int u, int v){ G[now].v = v; G[now].nxt = head[u]; head[u] = now ++; } void Tarjan(int u){ Dfn[u] = Low[u] = ++ Tarjan_tim; vis[u] = 1; Stack[++ Top] = u; for(int i = head[u]; ~ i; i = G[i].nxt){ int v = G[i].v; if(!Dfn[v]){ Tarjan(v); Low[u] = min(Low[u], Low[v]); } else if(vis[v]) Low[u] = min(Low[u], Dfn[v]); } if(Dfn[u] == Low[u]){ Bel_tim ++; Belong[u] = Bel_tim; vis[u] = 0; while(Stack[Top] != u){ Belong[Stack[Top]] = Bel_tim; vis[Stack[Top]] = 0; Top --; } Top --; } } void Build_G(){ for(int u = 1; u <= n; u ++){ for(int i = head[u]; ~ i; i = G[i].nxt){ int v = G[i].v; if(Belong[u] != Belong[v]){ Out[Belong[u]] ++; In[Belong[v]] ++; } } } } int main() { n = read(); for(int i = 1; i <= n; i ++) head[i] = -1; for(int i = 1; i <= n; i ++){ int v = read(); while(v) { add(i, v); v = read(); } } for(int i = 1; i <= n; i ++) if(!Dfn[i]) Tarjan(i); Build_G(); int Out_js(0), In_js(0); for(int i = 1; i <= Bel_tim; i ++){ if(!Out[i]) Out_js ++; if(!In[i]) In_js ++; } if(Bel_tim == 1) cout << "1" << "\n" << "0"; else cout << In_js << "\n" << max(Out_js, In_js); return 0; }