[poj1236]Network of Schools(targin缩点SCC)

题意:有N个学校,从每个学校都能从一个单向网络到另外一个学校。
1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

解题关键:1、缩点之后求出入度为0的点的个数;

     2、缩点之后入度为0点和出度为0点的个数的max,(因为是任意点可到达全图),若存在点到达全图,添加入度-1条边即可。

注意特判只有一个节点的情况。

dfn需要初始化

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 typedef long long ll;
 9 #define MAXN 120
10 #define MAXM 100010
11 struct edge{
12     int to,nxt;
13 }e[MAXM];
14 int degree1[MAXN],degree2[MAXN];
15 int head[MAXN],st[MAXN],dfn[MAXN],lowest[MAXN],belong[MAXN];
16 bool inst[MAXN];
17 int n,scnt,top,tot;//scnt从1开始
18 void init(){
19     memset(head,-1,sizeof head);
20     memset(degree1,0,sizeof degree1);
21     memset(degree2,0,sizeof degree2);
22     scnt=top=tot=0;
23 }
24 
25 void add_edge(int u, int v){
26     e[tot].to=v;
27     e[tot].nxt=head[u];
28     head[u]=tot++;
29 }
30 
31 void Tarjan(int u){
32     dfn[u]=lowest[u]=++tot;
33     inst[u]=1;
34     st[top++]=u;
35     for(int i=head[u];i!=-1;i=e[i].nxt){
36         int v=e[i].to;
37         if(!dfn[v]){
38             Tarjan(v);
39             lowest[u]=min(lowest[u],lowest[v]);
40         }
41         else if(inst[v]){
42             lowest[u]=min(lowest[u],dfn[v]);//也可用lowest
43         }
44     }
45     if(dfn[u]==lowest[u]){
46         scnt++;
47         int t;
48         do{
49             t=st[--top];
50             inst[t]=false;
51             belong[t]=scnt;
52         }while(t!=u);
53     }
54 }
55 
56 void solve(){//缩点
57     for(int i=1;i<=n;i++)  if(!dfn[i])  Tarjan(i);
58     for(int i=1;i<=n;i++){
59         for(int j=head[i];j!=-1;j=e[j].nxt){
60             if(belong[i]!=belong[e[j].to]){
61                 degree1[belong[i]]++,degree2[belong[e[j].to]]++;
62             }
63         }
64     }
65     int sum1=0,sum2=0;
66     for(int i=1;i<=scnt;i++){
67         if(!degree1[i]) sum1++;
68         if(!degree2[i]) sum2++;
69     }
70     if(scnt==1){//1个节点进行特判 
71         printf("1
0
");
72         return;
73     }
74     printf("%d
",sum2);
75     printf("%d
",max(sum1,sum2));
76     return;
77 }
78 
79 int main(){
80     int a;
81     while(scanf("%d",&n)!=EOF){
82         init();
83         int m=1;
84         while(scanf("%d",&a)){
85             if(a==0){
86                 m++;
87                 if(m>n) break;
88                 continue;
89             }
90             add_edge(m,a);
91         }
92         solve();
93     }
94     return 0;
95 }
原文地址:https://www.cnblogs.com/elpsycongroo/p/7566287.html