强连通。。。

前两天比赛的题目, 当时不理解清题目, 以为是一个无向图,然后找环。。怎么搞都搞不出来。。。

今天上午看了一下强连通,,学习了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 }

 

posted on 2011-04-19 12:21  奋斗青春  阅读(427)  评论(0编辑  收藏  举报