校园网络 usaco

这道题和上一道【最受欢迎的牛】差不多,都是强连通分量的练习题;

第一问实际上就是问缩点后入度为0的点有多少,第二问就是问添加几条边能使缩点后的图变成强连通图;

第一问好做,第二问需要动下脑子,也不难;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<ctime>
 5 #include<cstring>
 6 #include<string>
 7 #include<algorithm>
 8 using namespace std;
 9 const int maxn=105;
10 int n,x,y,v;
11 struct node{
12     int y,next;
13 }e[maxn*maxn<<1];
14 int linkk[maxn],len=0;
15 int pre[maxn],low[maxn],scc_cnt=0,dfs_clock=0,z[maxn],top=0,in[maxn],out[maxn],sccno[maxn];
16 bool b[maxn][maxn];
17 void insert(int x,int y){
18     e[++len].y=y;
19     e[len].next=linkk[x];
20     linkk[x]=len;
21 }
22 void dfs(int x){
23     pre[x]=low[x]=++dfs_clock;
24     z[++top]=x;
25     for(int i=linkk[x];i;i=e[i].next){
26         if(!pre[e[i].y]){
27             dfs(e[i].y);
28             low[x]=min(low[x],low[e[i].y]);
29         }
30         else if(!sccno[e[i].y])low[x]=min(low[x],pre[e[i].y]);
31     }
32     if(low[x]==pre[x]){
33         scc_cnt++;
34         while(true){
35             sccno[z[top]]=scc_cnt;
36             if(z[top]==x){top--;break;}
37             top--;
38         }
39     }
40 }
41 void init(){
42     scanf("%d",&n);
43     for(int i=1;i<=n;i++){
44         while(scanf("%d",&x)&&x)insert(i,x);
45     }
46 }
47 void slove(){
48     for(int i=1;i<=n;i++)if(!pre[i])dfs(i);
49     for(int j=1;j<=n;j++)
50         for(int i=linkk[j];i;i=e[i].next){
51             x=sccno[j],y=sccno[e[i].y];
52             if(x==y||b[x][y])continue;
53             b[x][y]=1;in[y]++,out[x]++;
54         }
55     x=0,y=0;
56     for(int i=1;i<=scc_cnt;i++){
57         if(!in[i])x++;
58         if(!out[i])y++;
59     }
60     printf("%d\n%d\n",x,scc_cnt==1?0:max(x,y));
61 }
62 int main(){
63     //freopen("1.in","r",stdin);
64     //freopen("1.out","w",stdout);
65     init();
66     slove();
67 }
View Code

 

posted @ 2016-09-02 12:35  CHADLZX  阅读(147)  评论(0编辑  收藏  举报