• 有向连通图增加多少边构成强联通(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);
         }
    }
    


  • 相关阅读:
    __attribute__ 总结
    linux文件夹打包命令
    学习ARM的一些基本知识,个人整理
    备忘录之 —— .bashrc(IC工具篇)
    GitHub的基本使用
    02: SocketServer服务
    01: socket模块
    08: python基础练习题
    07: 高阶函数&异常处理
    06: 面向对象
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348258.html
Copyright © 2020-2023  润新知