构造强连通图

 

  

  我们知道,要把一个非边双连通图构造成一个边双连通图,只需把这个图化简(边双连通分量缩点)成一个树,然后 找出叶子节点个数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

 

你可能感兴趣的:(图)