😿 😿 😿
第二个问题是最少加多少边把一个有向图变成强连通图
(1)缩点之后统计每个点的入度和出度
(2)定义入度为0的点(起点)的个数为src,出度为0的点的个数为des,要送到所有的学校,只要在每个起点放一个即可
(3)转换强连通图,只要将所有的起点终点连到其他连通分量的终点起点即可
int n;
vector<int>mp[111];
int tot,dfn[111],low[111];//时间戳
int cnt,id[111];//为找到的连通分量编号
int inst[111];//是否还在栈中
stack<int>st;
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
st.push(x);
inst[x]=1;
for(auto v:mp[x])
{
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);//如果lowv小于lowx说明
}
else if(inst[v])//还在栈中,说明v的强连通分量还没有找完
low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x])
{
int v=st.top();
++cnt;
do
{
v=st.top();st.pop();
id[v]=cnt,inst[v]=0;
} while (v!=x);
}
}
int out[111],in[111];
signed main()
{
cin>>n;
rpp(u,n)
{
int v;
while(cin>>v,v)
mp[u].push_back(v);
}
rpp(i,n) if(!dfn[i]) tarjan(i);
//统计度数
rpp(i,n)
for(auto v:mp[i])
if(id[v]!=id[i]) ++out[id[i]],++in[id[v]];
int src=0,des=0;
rpp(i,cnt)
{
if(!in[i]) ++src;
if(!out[i]) ++des;
}
cout<<src<<endl;
if(cnt==1) cout<<0<<endl;
else cout<<max(src,des)<<endl;
stop;
return 0;
}