题目大意:有N个学校,从每个学校都能从一个单向网络到另外一个学校,两个问题
1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
解题思路:
首先找连通分量,然后看连通分量的入度为0点的总数,出度为0点的总数,那么问要向多少学校发放软件,就是入度为零的个数,这样才能保证所有点能够找到
1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
解题思路:
首先找连通分量,然后看连通分量的入度为0点的总数,出度为0点的总数,那么问要向多少学校发放软件,就是入度为零的个数,这样才能保证所有点能够找到
然后第二问添加多少条边可以得到使整个图达到一个强连通分量,答案是入度为0的个数和出度为0的个数中最大的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
using namespace std;
#define LL long long
#define MAX 10000+5
const int INF=0x3f3f3f3f;
const double inf=1e18;
int in[105];
int out[105];
struct Edge{
int next,to;
}edge[50005];
int node[MAX];
int DFN[MAX];
int low[MAX];
int instack[MAX];
int sstack[MAX];
int belong[MAX];
int e[105][105];
int top;
int index;
int ecnt;
int bcnt;
void add_edge(int from,int to){
edge[ecnt].next=node[from];
edge[ecnt].to=to;
node[from]=ecnt++;
}
void tarjan(int u){
DFN[u]=low[u]=++index;
instack[u]=1;
sstack[++top]=u;
for(int i=node[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!DFN[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]) low[u]=min(low[u],DFN[v]);
}
if(low[u]==DFN[u]){
bcnt++;
while(1){
int j=sstack[top--];
instack[j]=0;
belong[j]=bcnt;
if(j==u) break;
}
}
}
int main(){
int n;
scanf("%d",&n);
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(node,-1,sizeof(node));
memset(instack,0,sizeof(instack));
memset(DFN,0,sizeof(DFN));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(e,0,sizeof(e));
for(int i=1;i<=n;i++){
int a;
while(scanf("%d",&a)&&a){
add_edge(i,a);
e[i][a]=1;
}
}
top=0;
index=0;
bcnt=0;
for(int i=1;i<=n;i++){
if(!DFN[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(e[i][j]&&belong[i]!=belong[j]){
in[belong[j]]++;
out[belong[i]]++;
}
}
}
int num1=0,num2=0;
for(int i=1;i<=bcnt;i++){
if(!in[i]) num1++;
if(!out[i]) num2++;
}
if(bcnt==1) printf("1\n0\n");
else printf("%d\n%d\n",num1,max(num1,num2));
return 0;
}