#include<bits/stdc++.h>
using namespace std;
const int N = 110, M = 1e4 + 10;
int h[N], e[M], ne[M], idx;
int n, m;
bool is_stk[N];
int stk[N];
int top;
int low[N], dfn[N], timep;
int scc_cnt;
int id[N];
int din[N], dout[N];
void add(int a, int b){
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++ ;
}
void tarjan(int u){
low[u] = dfn[u] = ++ timep;
stk[ ++ top] = u;
is_stk[u] = true;
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if(!dfn[j]){
tarjan(j);
low[u] = min(low[u], low[j]);
}
else if(is_stk[j]) low[u] = min(low[u], dfn[j]);
}
if(low[u] == dfn[u]){
int y;
++ scc_cnt;
do{
y = stk[top -- ];
id[y] = scc_cnt;
is_stk[y] = false;
}while(y != u);
}
}
int main()
{
cin>>n;
memset(h, -1, sizeof h);
for(int i = 1; i <= n; i ++ ){
int t;
while(cin>>t, t) add(i, t);
}
for(int i = 1; i <= n; i ++ ){
if(!dfn[i]){
tarjan(i);
}
}
for(int i = 1; i <= n; i ++ ){
for(int j = h[i]; ~j; j = ne[j]){
int k = e[j];
int a = id[i], b = id[k];
if(a != b){
din[b] ++ ;
dout[a] ++ ;
}
}
}
//记录起点数、终点数
int op1 = 0, op2 = 0;
for(int i = 1; i <= scc_cnt; i ++ ){
if(!din[i]) op1 ++ ;
if(!dout[i]) op2 ++ ;
}
cout<<op1<<endl;
if(scc_cnt == 1) puts("0");
else cout<<max(op1, op2)<<endl;
return 0;
}
AcWing 367. 学校网络 题解(tarjan dfs序时间戳+缩环成点)
最新推荐文章于 2024-05-23 11:51:48 发布