hdu 2767强连通分量练习

判断强连通图之后,果断要做做强连通分量的题目,之前做求割点的题目的时候就已经学过了tarjan算法了。。  但是还是不会用,一开始看到这个题目的时候不知道怎么办,感觉就是有种怪怪的感觉。。  看了网上的代码,出度和入度的判断真的还蛮精妙的。。 

通过一边tarjan算法已经将一个图分解成了很多个前连通图了。。。  这要计算出每一个前连通分量的入度和出度来,然后添加的边只要能使所有强连通分量连通就可以。。所以只用添加max(入度缺少,出度缺少)。。

View Code
 1   #include<iostream>
 2   #define min(a,b) a<b?a:b
 3   #define max(a,b) a>b?a:b
 4   using namespace std;
 5   struct node
 6   {
 7      int e,next;       
 8   }edge[50002];
 9   int head[20002],exist[20002],dfn[20002],low[20002],stack[20002],weight[20002],n,m,s,e,top,Count,Time;
10   int ind[20002],outd[20002];
11   void tarjan(int u) 
12   {
13        stack[top++]=u;
14        dfn[u]=low[u]=++Time;
15        exist[u]=1;
16        for(int end=head[u];end!=-1;end=edge[end].next)
17        {
18            if(!dfn[edge[end].e])
19            {
20                tarjan(edge[end].e);
21                low[u]=min(low[u],low[edge[end].e]);      
22            }        
23            else
24            {
25                if(exist[edge[end].e]==1)
26                low[u]=min(low[u],dfn[edge[end].e]);
27            }
28        }
29        if(dfn[u]==low[u])
30        {
31            while(u!=stack[top])
32            {
33               weight[stack[top-1]]=Count;
34               exist[stack[top-1]]=0;
35               top--;
36            }
37            Count++;
38        }
39   }
40   int main()
41   {
42      int t;
43      scanf("%d",&t);
44      while(t--)
45      {
46             scanf("%d%d",&n,&m);
47             for(int i=0;i<=n;i++)
48             {
49                 head[i]=-1;
50                 ind[i]=outd[i]=exist[i]=weight[i]=low[i]=dfn[i]=0; 
51             }
52             Time=top=Count=0;
53             for(int i=0;i<m;i++)
54             {
55                 scanf("%d%d",&s,&e);
56                 edge[i].e=e;
57                 edge[i].next=head[s];
58                 head[s]=i;
59             }
60             for(int i=1;i<=n;i++)
61             {
62                if(!dfn[i])
63                {
64                       tarjan(i);
65                }        
66             }
67             if(Count==1){printf("0\n");continue;}
68             else
69             {
70              for(int i=1;i<=n;i++)
71             {
72                for(int end=head[i];end!=-1;end=edge[end].next)
73                {
74                   if(weight[i]!=weight[edge[end].e])
75                   {
76                          ind[weight[edge[end].e]]++;
77                          outd[weight[i]]++;
78                   }
79                }        
80             }
81              int maxin=0,maxout=0;
82              for(int i=0;i<Count;i++)
83              {
84                 if(ind[i]==0)maxout++;
85                 if(outd[i]==0)maxin++;
86              }
87             printf("%d\n",max(maxout,maxin));
88            }
89      }
90      return 0;    
91   }

 

posted @ 2012-09-01 21:47  诺小J  阅读(185)  评论(0编辑  收藏  举报