强连通。。。
前两天比赛的题目, 当时不理解清题目, 以为是一个无向图,然后找环。。怎么搞都搞不出来。。。
今天上午看了一下强连通,,学习了Kosaraju这个算法。。
题目大意是给你一个有向图,问你至少加几条边让整个图变成强连通,,强连通图的意思是图里面任意两个顶点都能够到达,,
解法:缩点后统计没有出度的和没有入度的点个个数,两者取最大值
代码:
View Code
1 # include<stdio.h> 2 # include<string.h> 3 # define PI 50005 4 # define M 20005 5 struct node{ 6 int from,to,next; 7 }edge1[PI],edge2[PI]; 8 int head1[M],head2[M],visit1[M],visit2[M],T[M]; 9 int Blong[M],in_degree[M],out_degree[M],Tcnt,Bcnt,tol1,tol2; 10 void add(int a,int b) 11 { 12 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++; 13 /*以空间换空间(二维的指定不行,所以就申请多个空间,同样达到记录有向边的效果)*/ 14 edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++; 15 /*保存前驱*/ 16 } 17 void dfs1(int i) 18 { 19 int j; 20 visit1[i]=1; 21 for(j=head1[i];j!=-1;j=edge1[j].next) 22 { 23 if(visit1[edge1[j].to]==0) dfs1(edge1[j].to); 24 } 25 T[Tcnt++]=i; 26 } 27 void dfs2(int i) 28 { 29 int j; 30 Blong[i]=Bcnt; 31 visit2[i]=1; 32 for(j=head2[i];j!=-1;j=edge2[j].next) 33 { 34 if(visit2[edge2[j].to]==0) dfs2(edge2[j].to); 35 } 36 } 37 int main() 38 { 39 int i,n,m,ncase,in,out,a,b,x,y; 40 scanf("%d",&ncase); 41 while(ncase--) 42 { 43 scanf("%d%d",&n,&m); 44 tol1=0; 45 tol2=0; 46 Tcnt=0; 47 Bcnt=0;/*表示强连通分支的数目*/ 48 for(i=1;i<=n;i++) 49 { 50 head1[i]=-1; 51 head2[i]=-1; 52 visit1[i]=0; 53 visit2[i]=0; 54 } 55 while(m--) 56 { 57 scanf("%d%d",&a,&b); 58 add(a,b); 59 } 60 for(i=1;i<=n;i++) 61 if(visit1[i]==0) dfs1(i); 62 for(i=Tcnt-1;i>=0;i--) 63 { 64 /*如果不存在环的情况下,最外层的入度为0*/ 65 if(visit2[T[i]]==0) 66 { 67 dfs2(T[i]); 68 Bcnt++;/*找到一个强连通分支*/ 69 } 70 } 71 for(i=0;i<Bcnt;i++) 72 { 73 in_degree[i]=0; 74 out_degree[i]=0; 75 } 76 for(i=0;i<tol1;i++) 77 { 78 x=Blong[edge1[i].from]; 79 y=Blong[edge1[i].to]; 80 if(x!=y) 81 {/*判断是否已经在一个强连通分支里面了*/ 82 out_degree[x]=1; 83 in_degree[y]=1; 84 } 85 } 86 in=0; 87 out=0; 88 for(i=0;i<Bcnt;i++) 89 { 90 if(in_degree[i]==0) in++; 91 if(out_degree[i]==0) out++; 92 } 93 if(Bcnt==1) printf("0\n"); 94 else printf("%d\n",in>out?in:out); 95 } 96 return 0; 97 }