题意:有 n 个学校每个学校可以将自己的软件共享给其他一些学校,首先,询问至少将软件派发给多少学校能够使软件传播到所有学校,其次,询问添加多少学校共享关系可以使所有学校的软件能够相互传达。

首先,第一个问题首先就做强连通缩点,对于缩点后的图询问有多少点的入度为 0,因为入度为 0 的分量必然不能通过其他点传达到。第二个问题则是询问入度为 0 和出度为 0 的点个数的最大值。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stack>
 4 #include<queue>
 5 using namespace std;
 6 
 7 const int maxn=100;
 8 const int maxm=1e4+5;
 9 
10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
11 int n,t,scccnt;
12 int stx[maxn],low[maxn],scc[maxn];
13 int id[maxn],od[maxn];
14 stack<int>S;
15 
16 int max(int a,int b){return a>b?a:b;}
17 
18 void init(){
19     memset(head,-1,sizeof(head));
20     size[0]=size[1]=0;
21     memset(id,0,sizeof(id));
22     memset(od,0,sizeof(od));
23 }
24 
25 void add(int a,int b,int c=0){
26     point[c][size[c]]=b;
27     nxt[c][size[c]]=head[c][a];
28     head[c][a]=size[c]++;
29 }
30 
31 void dfs(int s){
32     stx[s]=low[s]=++t;
33     S.push(s);
34     for(int i=head[0][s];~i;i=nxt[0][i]){
35         int j=point[0][i];
36         if(!stx[j]){
37             dfs(j);
38             low[s]=min(low[s],low[j]);
39         }
40         else if(!scc[j]){
41             low[s]=min(low[s],stx[j]);
42         }
43     }
44     if(low[s]==stx[s]){
45         scccnt++;
46         while(1){
47             int u=S.top();S.pop();
48             scc[u]=scccnt;
49             if(s==u)break;
50         }
51     }
52 }
53 
54 void setscc(){
55     memset(stx,0,sizeof(stx));
56     memset(scc,0,sizeof(scc));
57     t=scccnt=0;
58     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
59     for(int i=1;i<=n;++i){
60         for(int j=head[0][i];~j;j=nxt[0][j]){
61             int k=point[0][j];
62             if(scc[i]!=scc[k]){
63                 add(scc[i],scc[k],1);
64                 od[scc[i]]++;
65                 id[scc[k]]++;
66             }
67         }
68     }
69 }
70 
71 int main(){
72     scanf("%d",&n);
73     init();
74     for(int i=1;i<=n;++i){
75         int b;
76         while(scanf("%d",&b)&&b){
77             add(i,b);
78         }
79     }
80     setscc();
81     int in=0,out=0;
82     for(int i=1;i<=scccnt;++i){
83         if(!id[i])in++;
84         if(!od[i])out++;
85     }
86     printf("%d\n%d\n",in,scccnt==1?0:max(in,out));
87     return 0;
88 }
View Code