有向连通图增加多少边构成强联通(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
");
               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
",max1>max2?max1:max2);
     }
}


原文地址:https://www.cnblogs.com/mypsq/p/4348258.html