hdu 2767 Proving Equivalences(强连通 缩点 以及判断入度 出度)
题意
补最少的边成强连通图。
缩点后,max{ 入度为0点数, 出度为零点数}即为所求的值
(vector,belong,DFN,LOW)

1 #include<stdio.h> 2 #include<vector> 3 #include<string.h> 4 using namespace std; 5 vector <int> Q[20005],R[20005]; 6 int x,y,Num; 7 bool instack[20005]; //标记在栈里的元素 8 int stack[20005]; //存储当前在栈里的元素 9 int low[20005],DFN[20005]; //DFN表示该数被访问的顺序;low值更新为一个强连通里面最开始访问的那个数的顺序(所以一开始low值与DFN的值相同); 10 int belong[20005]; //将处于同一个强连通的所有分量赋相同的值存于其中 11 int in[20005],out[20005]; //缩点之后 判断是否存在入度或者出度 12 13 void Init_tarjan(int n) 14 { 15 x=0;y=0;Num=0; 16 for(int i=1;i<=n;i++) 17 { 18 Q[i].clear(); 19 R[i].clear(); 20 } 21 memset(low,0,sizeof(low)); 22 memset(DFN,0,sizeof(DFN)); 23 memset(in,0,sizeof(in)); 24 memset(out,0,sizeof(out)); 25 memset(belong,0,sizeof(belong)); 26 memset(instack,false,sizeof(instack)); 27 } 28 29 void tarjan(int i) 30 { 31 DFN[i]=low[i]=++y; //为节点i设定次序编号和Low初值 //如果初始化为0;不能写成y++; 32 stack[++x]=i; //压入栈中 33 instack[i]=true; //标记在栈中的元素 34 for(int j=0;j<Q[i].size();j++) 35 { 36 int k=Q[i][j]; 37 if(!DFN[k]) 38 { 39 tarjan(k); //未被访问过,调用此函数 40 low[i]=min(low[i],low[k]); //更新low值 41 } 42 else if(instack[k]) 43 { 44 low[i]=min(low[i],DFN[k]);//访问到已在栈中的元素,比较访问的顺序,去较小的一个。 45 } 46 } 47 if(DFN[i]==low[i]) 48 { 49 Num++; //记录强连通分量个数 50 int j; 51 do 52 { 53 j=stack[x--]; 54 belong[j]=Num; //将处于同一个强连通的所有分量赋相同的值 55 instack[j]=false; 56 }while(j!=i); //到删除DFN值和low值相同的点截止 57 } 58 }//求强连通分量个数 59 60 void Creat_New_Grap(int n) 61 { 62 for(int i=1;i<=n;i++) 63 { 64 for(int j=0;j<Q[i].size();j++) 65 { 66 int k=Q[i][j]; 67 if(belong[k]!=belong[i]) //有指向其他强连通分量的边 68 R[belong[i]].push_back(belong[k]); 69 } 70 } 71 for(int i=1;i<=Num;i++) 72 { 73 for(int j=0;j<R[i].size();j++) 74 { 75 int k=R[i][j]; 76 in[k]=1; //第k个强连通分量有入度 77 out[i]=1; //第i个强连通分量有出度 78 } 79 } 80 }//缩点建新图 81 82 int main() 83 { 84 int N; 85 scanf("%d",&N); 86 while(N--) 87 { 88 int i,j,n,m,a,b; 89 scanf("%d %d",&n,&m); 90 Init_tarjan( n); 91 for(i=1;i<=m;i++) 92 { 93 scanf("%d %d",&a,&b); 94 Q[a].push_back(b); 95 } 96 for(i=1;i<=n;i++) 97 if(!DFN[i]) 98 tarjan(i); 99 if(Num==1) printf("0\n"); 100 else 101 { 102 Creat_New_Grap(n); 103 int X=0,Y=0; 104 for(i=1;i<=Num;i++) 105 { 106 if(in[i]==0) X++; 107 if(out[i]==0)Y++; 108 } 109 if(X>Y) printf("%d\n",X); 110 else printf("%d\n",Y); 111 } 112 113 } 114 }