nyoj 120 校园网络

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=120

也就是求添加多少条边可以构成强连通,有向图。方法是有trajan之后缩点,看新构成的图出度或者入度为零,大的即为要加的边。有主意图本身就连通是这是加的变为0,而不是1.

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <stack>
  5 using namespace std;
  6 const int MAX=105;
  7 int map[MAX][MAX];
  8 int low[MAX],DFN[MAX],IN[MAX],OUT[MAX],vist[MAX],t[MAX];
  9 int n,idenx,res,ans;
 10 stack<int>Q;
 11 void init()
 12 {
 13     memset(map,0,sizeof(map));
 14     memset(low,0,sizeof(low));
 15     memset(DFN,0,sizeof(DFN));
 16     memset(IN,0,sizeof(IN));
 17     memset(OUT,0,sizeof(OUT));
 18     memset(vist,0,sizeof(vist));
 19     memset(t,0,sizeof(t));
 20     while(!Q.empty())Q.pop();
 21     res=0;
 22     idenx=0;
 23 }
 24 int min(int x,int y)
 25 {
 26     if(x>y)return y;
 27     else return x;
 28 }
 29 void tr(int u)
 30 {
 31     int i,v;
 32     DFN[u]=low[u]=++idenx;
 33     vist[u]=1;
 34     Q.push(u);
 35     for (i=1;i<=n;i++)
 36     if(map[u][i]){
 37         if(!DFN[i])
 38         {
 39             tr(i);
 40             low[u]=min(low[u],low[i]);
 41         }
 42         else if(vist[i])
 43             low[u]=min(low[u],DFN[i]);
 44     }
 45 
 46     if(DFN[u]==low[u])
 47     {
 48         ++res;
 49        do {
 50            v=Q.top();
 51         Q.pop();
 52         vist[v]=0;
 53         t[v]=res;
 54        } while(v!=u);
 55     }
 56 }
 57 void trajan()
 58 {
 59     int i;
 60     for (i=1;i<=n;i++)
 61     if(!DFN[i]){
 62         tr(i);
 63     }
 64 }
 65 void solve()
 66 {
 67     int i,j,xx,yy;
 68     for (i=1;i<=n;i++)
 69         for (j=1;j<=n;j++)
 70         if(map[i][j]){
 71             IN[t[i]]++;
 72             OUT[t[j]]++;
 73         }
 74         xx=yy=0;
 75         for(i=1;i<=res;i++)
 76             if(IN[i]==0)xx++;
 77             else if(OUT[i]==0)yy++;
 78 
 79             ans=xx>yy?xx:yy;
 80 
 81 }
 82 int main()
 83 {
 84     int i,k,x;
 85     scanf("%d",&k);
 86     while (k--)
 87     {
 88         init();
 89         scanf("%d",&n);
 90         for (i=1;i<=n;i++)
 91         {
 92             while (scanf("%d",&x)&&x)
 93             {
 94                 map[i][x]=1;
 95             }
 96         }
 97         trajan();
 98         solve();
 99         if(res==1)printf("0\n");
100         else printf("%d\n",ans);
101     }
102     return 0;    
103 }

 

posted @ 2012-04-26 17:38  我们一直在努力  阅读(152)  评论(0编辑  收藏  举报