nyoj 120 校园网络
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=120
也就是求添加多少条边可以构成强连通,有向图。方法是有trajan之后缩点,看新构成的图出度或者入度为零,大的即为要加的边。有主意图本身就连通是这是加的变为0,而不是1.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }