构造强连通图

 

  

  我们知道,要把一个非边双连通图构造成一个边双连通图,只需把这个图化简(边双连通分量缩点)成一个树,然后 找出叶子节点个数leaf,(leaf+1)/2就是要新添加的边数。

  现在,对与有向图来说,我们需要求加最少的边,使得一个非强连通图变成一个强连通图,最少的边数是多少?

  同样的,我们需要把他化简(强连通分量缩点)成一个DAG图(有向无环图),然后找出入度为0的顶点个数in,和出度为0的顶点个数out,取他们的最大值就是需要添加的最少的边数。

  对于一种特殊情况,若原图中本身就是一个强连通图,那么缩点后的DGA图就是一个孤立的点,in和out分别等于1,按上述方式求的答案为1,显然和正确答案0不同,所以,我们在此特判一下即可。

 

  poj 1236

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 #define _Clr(x, y) memset(x, y, sizeof(x))
  6 #define INF 0x3f3f3f3f
  7 #define N 110
  8 using namespace std;
  9 
 10 struct Node
 11 {
 12     int to, next;
 13 }edge[N*100];
 14 int head[N], tot;
 15 int dfn[N], low[N];
 16 int Sta[N], bleg[N];
 17 bool instack[N];
 18 int n, cnt, top, ght;
 19 
 20 void Init()
 21 {
 22     cnt=tot=top=ght=0;
 23     _Clr(head, -1);
 24     _Clr(dfn, 0);
 25     _Clr(instack, 0);
 26 }
 27 
 28 void Add_edge(int a, int b)
 29 {
 30     edge[tot].to = b;
 31     edge[tot].next = head[a];
 32     head[a] = tot++;
 33 }
 34 
 35 void dfs(int u)
 36 {
 37     dfn[u]=low[u]=++cnt;
 38     instack[u] = true;
 39     Sta[top++] = u;
 40     for(int i=head[u]; i!=-1; i=edge[i].next)
 41     {
 42         int v = edge[i].to;
 43         if(!dfn[v])
 44         {
 45             dfs(v);
 46             low[u] = min(low[u], low[v]);
 47         }
 48         else if(instack[v]) low[u] = min(low[u], dfn[v]);
 49     }
 50     if(low[u]==dfn[u])
 51     {
 52         ght++;
 53   //      printf("Num:%d\n",ght);
 54         int v;
 55         do
 56         {
 57             v = Sta[--top];
 58     //        printf("%d ", v);
 59             instack[v] = false;
 60             bleg[v] = ght;
 61         }while(u != v);
 62       //  puts("");
 63     }
 64 }
 65 
 66 int inde[N], outde[N];
 67 void Tarjan()
 68 {
 69     for(int i=1; i<=n; i++)
 70         if(!dfn[i]) dfs(i);
 71 
 72     _Clr(inde, 0);
 73     _Clr(outde, 0);
 74     for(int u=1; u<=n; u++)
 75     for(int i=head[u];  i!=-1; i=edge[i].next)
 76     {
 77         int v = edge[i].to;
 78         if(bleg[v] != bleg[u])
 79             inde[bleg[v]]++, outde[bleg[u]]++;
 80     }
 81 }
 82 
 83 void Solved()
 84 {
 85     int a=0, b=0;
 86     if(ght==1)
 87         printf("1\n0\n");
 88     else
 89     {
 90         for(int i=1; i<=ght; i++)
 91         {
 92             if(inde[i]==0) a++;
 93             if(outde[i]==0) b++;
 94         }
 95         printf("%d\n%d\n", a, max(a, b));
 96     }
 97 }
 98 int main()
 99 {
100     int b;
101     while(~scanf("%d", &n))
102     {
103         Init();
104         for(int i=1; i<=n; i++)
105         {
106             while(scanf("%d", &b) && b)
107                 Add_edge(i, b);
108         }
109         Tarjan();
110         Solved();
111     }
112     return 0;
113 }
View Code

 

posted @ 2015-03-28 16:17  无道圣君  阅读(766)  评论(0编辑  收藏  举报