有向连通图增加多少边构成强联通(hdu3836,poj1236)

hdu3836

求出强分量后缩点处理得到分支图,对分支图的每个强连通分量统计出度和入度。需要的边数就是:统计 入度=0 的顶点数 和 出度=0 的顶点数,选择两者中较大的一个,才能确保一个强连通图。

程序:

 

#include"string.h"

#include"stdio.h"

#include"iostream"

#include"stack"

#define inf 999999999

#define M 20009

using namespace std;

stack<int>q;

struct st

{

     int u,v,next;

}edge[M*3];

int belong[M],head[M],low[M],dfn[M],use[M],out[M],in[M],index,num,t,n;

void init()

{

     t=0;

     memset(head,-1,sizeof(head));

}

void add(int u,int v)

{

     edge[t].u=u;

     edge[t].v=v;

     edge[t].next=head[u];

     head[u]=t++;

}

void tarjan(int u)

{

     dfn[u]=low[u]=++index;

     q.push(u);

     use[u]=1;

     int i;

     for(i=head[u];i!=-1;i=edge[i].next)

     {

          int v=edge[i].v;

          if(!dfn[v])

          {

               tarjan(v);

               low[u]=min(low[u],low[v]);

          }

          else if(use[v])

          {

               low[u]=min(low[u],dfn[v]);

          }

     }

     if(low[u]==dfn[u])

     {

          int p;

          num++;

          do

          {

               p=q.top();

               belong[p]=num;

               use[p]=0;

               q.pop();

          }while(u!=p);

     }

}

void solve()

{

     index=num=0;

     memset(dfn,0,sizeof(dfn));

     memset(use,0,sizeof(use));

     for(int i=1;i<=n;i++)

     {

          if(!dfn[i])

          {

               tarjan(i);

          }

     }

}

int main()

{

     int m,i;

     while(scanf("%d%d",&n,&m)!=-1)

     {

          init();

          while(m--)

          {

               int a,b;

               scanf("%d%d",&a,&b);

               add(a,b);

          }

          solve();

          if(num==1)//注意

          {

               printf("0\n");

               continue;

          }

          memset(out,0,sizeof(out));

          memset(in,0,sizeof(in));

          for(i=0;i<t;i++)

          {

               int u=edge[i].u;

               int v=edge[i].v;

               if(belong[u]!=belong[v])

               {

                    out[belong[u]]++;

                    in[belong[v]]++;

               }

          }

          int max1,max2;

          max1=max2=0;

          for(i=1;i<=num;i++)

          {

               if(out[i]==0)

                    max1++;

               if(in[i]==0)

                    max2++;

          }

          printf("%d\n",max1>max2?max1:max2);

     }

}


 

你可能感兴趣的:(poj)