题意 :给你一个学校的单向连通图,1:问你至少选几个学校发放软件才能使全部学校都收到,2:问你至少添加几条边才能使全部的学校够成一个强连通分量
题解:求出强连通分量个数,然后找到强量通分量入度为0的个数res,这是第一个的答案(注意只有一个强连通分量的情况),然后找到出度为0的强连通分量个数res1,max(res,res1)就是答案;
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<vector>
#define pb push_back
#define ll long long
#define PI 3.14159265
using namespace std;
const int maxn=1e2+5;
vector<int>g[maxn];
vector<int>rg[maxn];
vector<int>vs;
bool vis[maxn];
bool out[maxn];
int cmp[maxn];
int N,M;
void dfs(int v)
{
vis[v]=true;
for(int i=0;i<g[v].size();i++)
{
if(!vis[g[v][i]])dfs(g[v][i]);
}
vs.pb(v);
}
void rdfs(int v,int k)
{
vis[v]=true;
cmp[v]=k;
for(int i=0;i<rg[v].size();i++)
{
if(!vis[rg[v][i]])rdfs(rg[v][i],k);
}
}
int scc()
{
for(int i=1;i<=N;i++)
{
if(!vis[i])dfs(i);
}
memset(vis,false,sizeof(vis));
int k=0;
for(int i=vs.size()-1;i>=0;i--)
{
if(!vis[vs[i]])rdfs(vs[i],k++);
}
return k;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>N;
for(int i=1;i<=N;i++)
{
int a;
while(cin>>a)
{
if(!a)break;
g[i].pb(a);
rg[a].pb(i);
}
}
int n=scc();
memset(vis,false,sizeof(vis));
for(int i=1;i<=N;i++)
{
for(int j=0;j<g[i].size();j++)
{
if(cmp[g[i][j]]!=cmp[i])
{
vis[cmp[g[i][j]]]=true;
out[cmp[i]]=true;
}
}
}
int res=0,res1=0;
for(int i=0;i<n;i++)
{
if(!vis[i])res++;
if(!out[i])res1++;
}
res1=max(res,res1);
res=res>0?res:1;
if(n==1)res1=0;
cout<<res<<'
'<<res1<<'
';
return 0;
}