zoukankan      html  css  js  c++  java
  • hdu2435最大流最小割

    2435  There is a war


    题意:
          给你一个有向图,其中可以有一条边是无敌的,这条边可以是图中的边,也可以是自己任意加上去的图中没有的边,这条无敌的边不可以摧毁,让1和n无法连通的最大摧毁费用,就是1到n的最小割中的最大的那个,这个题卡了好几天,一开始是各种方法各种wa,后来无意中发现自己犯了个sb错误,结果改正后以前的各种方法各种ac,比赛要是碰到这样的事估计就跪了...


    思路:
         首先能确定的就是题目要求咱们就最小割(最大流 = 最小割),但关键是有那么一条无坚不摧的nb道路,所以一开始的想法肯定是暴力枚举N*N的边,直接TLE出翔了,那么就优化,记得以前的一道题目 给你一个图求删除其中一条边最短路中最大的那个,答案是只枚举最短路上的边就可以了, 这个题目也是类似,只要枚举最小割后两个集合的点组成的边就行了,因为假如点a和点b是一个集合的,那么把边ab变成无敌的没有意思,最小割的值不会改变,,那么怎么吧分成两个集合呢,两种方法,一个是深搜,这个方法容易理解,先跑一遍最大流,然后从点1开始深搜,如果当前点走过或者没有流量了(跑完一遍最大流后的流量),直接continue,这样被mark的点就是左集合的点,剩下的就是右集合的点,还有一种方法就是直接看DINIC后的deep数组,如果不等于-1就是左集合的,否则的就是右集合的,这个我结论是网上的,我还不知道为什么,分成两个集合后就可以枚举两个集合的点建枚举的边了,这块也有两个方法,一个就是之前不是跑一边最大流了吗,加上当前枚举边,直接在残余网络上跑,取得最大的max最后输出一开始那个最大流maxflow+max,(记得每次跑之前都还原成第一次跑完的残余网路),第二种方法就是直接重新建边,一开始的时候吧m条边记录下来,每次枚举都重新建图,然后加上枚举的边跑,最后输出的是最大流中最大的那个maxflow.下面是三种方法的代码..




    深搜找源集和汇集,在残余网络上跑 15ms AC
    #include<stdio.h>
    #include<string.h>
    #include<queue>


    #define N_node 120

    #define N_edge 22000
    #define inf 1000000000


    using namespace std;


    typedef struct

    {
       int to ,next ,cost;
    }STAR;
    typedef struct
    {
       int x ,t;
    }DEP;


    STAR E[N_edge] ,E_[N_edge];
    DEP xin ,tou;
    int list[N_node] ,list1[N_node] ,tot;
    int list2[N_node];
    int deep[N_node];
    int mks[N_node] ,mks_;
    int mkh[N_node] ,mkh_;
    int mark[N_node];


    void add(int a ,int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
       
       E[++tot].to = a;
       E[tot].cost = 0;
       E[tot].next = list[b];
       list[b] = tot;
    }


    int minn(int a ,int b)
    {
       return a < b ? a : b;
    }


    bool BFS_DEEP(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        deep[s] = 0;
        xin.x = s;
        xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        while(!q.empty())
        {
          tou = q.front();
          q.pop();
          for(int k = list[tou.x] ;k ;k = E[k].next)
          {
             xin.x = E[k].to;
             xin.t = tou.t + 1;
             if(deep[xin.x] != -1 || !E[k].cost)
             continue;
             deep[xin.x] = xin.t;
             q.push(xin);
          }
       }
       for(int i = 0 ;i <= n ;i ++)
       list1[i] = list[i];
       return deep[t] != -1;
    }


    int DFS_MAX_FLOW(int s ,int t ,int flow)
    {
       if(s == t) return flow;
       int nowflow = 0;
       for(int k = list1[s] ;k ;k = E[k].next)
       {
          list1[s] = k;
          int to = E[k].to;
          int c = E[k].cost;
          if(deep[to] != deep[s] + 1||!E[k].cost)
          continue;
          int tmp = DFS_MAX_FLOW(to ,t ,minn(c ,flow - nowflow));
          nowflow += tmp;
          E[k].cost -= tmp;
          E[k^1].cost += tmp;
          if(nowflow == flow)
          break;
       }
       if(!nowflow)
       deep[s] = 0;
       return nowflow;
    }


    int DINIC(int s ,int t ,int n)
    {
       int ans = 0;
       while(BFS_DEEP(s ,t ,n))
       {
          ans += DFS_MAX_FLOW(s ,t ,inf);
       }
       return ans;
    }


    void DFS(int s)
    {
       for(int k = list[s] ;k ;k = E[k].next)
       {
          int to = E[k].to;
          if(mark[to] || !E[k].cost)
          continue;
          mark[to] = 1;
          DFS(to);
       }
       return ;
    }


    int main ()
    {
       int n ,m ,i ,j ,t;
       int a ,b ,c;
       scanf("%d" ,&t);
       while(t--)
       {
          memset(list ,0 ,sizeof(list));
          tot = 1;
          scanf("%d %d" ,&n ,&m);
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d" ,&a ,&b ,&c);
             add(a ,b ,c);
          }
          int ans = DINIC(1 ,n ,n);
          mks_ = mkh_ = 0;
          memset(mark ,0 ,sizeof(mark));
          mark[1] = 1;
          DFS(1);
          for(i = 2 ;i < n ;i ++)
          if(mark[i]) mks[++mks_] = i;
          else mkh[++mkh_] = i;
          
          for(i = 1 ;i <= tot ;i ++)
          E_[i] = E[i];
          int mktot = tot;
          for(i = 1 ;i <= n ;i ++)
          list2[i] = list[i];
          
          int max = 0;
          for(i = 1 ;i <= mks_ ;i ++)
          for(j = 1 ;j <= mkh_ ;j ++)
          {
             a = mks[i] ,b = mkh[j];
             for(int k = 1 ;k <= mktot ;k ++)
             E[k] = E_[k];
             memset(list ,0 ,sizeof(list));
             for(int k = 1 ;k <= n ;k ++)
             list[k] = list2[k];
             tot = mktot;
             add(a ,b ,inf);
             int tmp = DINIC(1 ,n ,n);
             if(max < tmp) max = tmp;
          }
          printf("%d " ,ans + max);
       }
       return 0;
    }
             
             
          
          
    根据deep数组找源集和汇集,在残余网络上跑 31ms AC

    #include<stdio.h>
    #include<string.h>
    #include<queue>


    #define N_node 120
    #define N_edge 22000
    #define inf 1000000000


    using namespace std;


    typedef struct
    {
       int to ,next ,cost;
    }STAR;
    typedef struct
    {
       int x ,t;
    }DEP;


    STAR E[N_edge] ,E_[N_edge];
    DEP xin ,tou;
    int list[N_node] ,list1[N_node] ,tot;
    int list2[N_node];
    int deep[N_node];
    int mks[N_node] ,mks_;
    int mkh[N_node] ,mkh_;


    void add(int a ,int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
       
       E[++tot].to = a;
       E[tot].cost = 0;
       E[tot].next = list[b];
       list[b] = tot;
    }


    int minn(int a ,int b)
    {
       return a < b ? a : b;
    }


    bool BFS_DEEP(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        deep[s] = 0;
        xin.x = s;
        xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        while(!q.empty())
        {
          tou = q.front();
          q.pop();
          for(int k = list[tou.x] ;k ;k = E[k].next)
          {
             xin.x = E[k].to;
             xin.t = tou.t + 1;
             if(deep[xin.x] != -1 || !E[k].cost)
             continue;
             deep[xin.x] = xin.t;
             q.push(xin);
          }
       }
       for(int i = 0 ;i <= n ;i ++)
       list1[i] = list[i];
       return deep[t] != -1;
    }


    int DFS_MAX_FLOW(int s ,int t ,int flow)
    {
       if(s == t) return flow;
       int nowflow = 0;
       for(int k = list1[s] ;k ;k = E[k].next)
       {
          list1[s] = k;
          int to = E[k].to;
          int c = E[k].cost;
          if(deep[to] != deep[s] + 1||!E[k].cost)
          continue;
          int tmp = DFS_MAX_FLOW(to ,t ,minn(c ,flow - nowflow));
          nowflow += tmp;
          E[k].cost -= tmp;
          E[k^1].cost += tmp;
          if(nowflow == flow)
          break;
       }
       if(!nowflow)
       deep[s] = 0;
       return nowflow;
    }


    int DINIC(int s ,int t ,int n)
    {
       int ans = 0;
       while(BFS_DEEP(s ,t ,n))
       {
          ans += DFS_MAX_FLOW(s ,t ,inf);
       }
       return ans;
    }


    int main ()
    {
       int n ,m ,i ,j ,t;
       int a ,b ,c;
       scanf("%d" ,&t);
       while(t--)
       {
          memset(list ,0 ,sizeof(list));
          tot = 1;
          scanf("%d %d" ,&n ,&m);
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d" ,&a ,&b ,&c);
             add(a ,b ,c);
          }
          int ans = DINIC(1 ,n ,n);
          mks_ = mkh_ = 0;
          for(i = 2 ;i < n ;i ++)
          if(deep[i] != -1) mks[++mks_] = i;
          else mkh[++mkh_] = i;
          
          for(i = 1 ;i <= tot ;i ++)
          E_[i] = E[i];
          int mktot = tot;
          for(i = 1 ;i <= n ;i ++)
          list2[i] = list[i];
          
          int max = 0;
          for(i = 1 ;i <= mks_ ;i ++)
          for(j = 1 ;j <= mkh_ ;j ++)
          {
             a = mks[i] ,b = mkh[j];
             for(int k = 1 ;k <= mktot ;k ++)
             E[k] = E_[k];
             memset(list ,0 ,sizeof(list));
             for(int k = 1 ;k <= n ;k ++)
             list[k] = list2[k];
             tot = mktot;
             add(a ,b ,inf);
             int tmp = DINIC(1 ,n ,n);
             if(max < tmp) max = tmp;
          }
          printf("%d " ,ans + max);
       }
       return 0;
    }
             
    直接重新建图,深搜找源集和汇集(容易理解) 15msAC


    #include<stdio.h>
    #include<string.h>
    #include<queue>


    #define N_node 120
    #define N_edge 22000
    #define inf 1000000000


    using namespace std;


    typedef struct
    {
       int to ,next ,cost;
    }STAR;
    typedef struct
    {
       int x ,t;
    }DEP;


    typedef struct
    {
       int a ,b ,c;
    }EDGE;


    STAR E[N_edge];
    EDGE edge[N_edge];
    DEP xin ,tou;
    int list[N_node] ,list1[N_node] ,tot;
    int deep[N_node];
    int mks[N_node] ,mks_;
    int mkh[N_node] ,mkh_;
    int mark[N_node];


    void add(int a ,int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
       
       E[++tot].to = a;
       E[tot].cost = 0;
       E[tot].next = list[b];
       list[b] = tot;
    }


    int minn(int a ,int b)
    {
       return a < b ? a : b;
    }


    bool BFS_DEEP(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        deep[s] = 0;
        xin.x = s;
        xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        while(!q.empty())
        {
          tou = q.front();
          q.pop();
          for(int k = list[tou.x] ;k ;k = E[k].next)
          {
             xin.x = E[k].to;
             xin.t = tou.t + 1;
             if(deep[xin.x] != -1 || !E[k].cost)
             continue;
             deep[xin.x] = xin.t;
             q.push(xin);
          }
       }
       for(int i = 0 ;i <= n ;i ++)
       list1[i] = list[i];
       return deep[t] != -1;
    }


    int DFS_MAX_FLOW(int s ,int t ,int flow)
    {
       if(s == t) return flow;
       int nowflow = 0;
       for(int k = list1[s] ;k ;k = E[k].next)
       {
          list1[s] = k;
          int to = E[k].to;
          int c = E[k].cost;
          if(deep[to] != deep[s] + 1||!E[k].cost)
          continue;
          int tmp = DFS_MAX_FLOW(to ,t ,minn(c ,flow - nowflow));
          nowflow += tmp;
          E[k].cost -= tmp;
          E[k^1].cost += tmp;
          if(nowflow == flow)
          break;
       }
       if(!nowflow)
       deep[s] = 0;
       return nowflow;
    }


    int DINIC(int s ,int t ,int n)
    {
       int ans = 0;
       while(BFS_DEEP(s ,t ,n))
       {
          ans += DFS_MAX_FLOW(s ,t ,inf);
       }
       return ans;
    }


    void DFS(int s)
    {
       for(int k = list[s] ;k ;k = E[k].next)
       {
          int to = E[k].to;
          if(mark[to] || !E[k].cost)
          continue;
          mark[to] = 1;
          DFS(to);
       }
       return ;
    }


    int main ()
    {
       int n ,m ,i ,j ,t;
       int a ,b ,c;
       scanf("%d" ,&t);
       while(t--)
       {
          memset(list ,0 ,sizeof(list));
          tot = 1;
          scanf("%d %d" ,&n ,&m);
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d" ,&a ,&b ,&c);
             add(a ,b ,c);
             edge[i].a = a ,edge[i].b = b ,edge[i].c = c;
          }
          int ans = DINIC(1 ,n ,n);
          mks_ = mkh_ = 0;
          memset(mark ,0 ,sizeof(mark));
          mark[1] = 1;
          DFS(1);
          for(i = 2 ;i < n ;i ++)
          if(mark[i]) mks[++mks_] = i;
          else mkh[++mkh_] = i;
          for(i = 1 ;i <= mks_ ;i ++)
          for(j = 1 ;j <= mkh_ ;j ++)
          {
             a = mks[i] ,b = mkh[j];
             memset(list ,0 ,sizeof(list));
             tot = 1;
             for(int k = 1 ;k <= m ;k ++)
             add(edge[k].a ,edge[k].b ,edge[k].c);
             add(a ,b ,inf);
             int tmp = DINIC(1 ,n ,n);
             if(ans < tmp) ans = tmp;
          }
          printf("%d " ,ans);
       }
       return 0;
    }

    
    

  • 相关阅读:
    四则运算2之单元测试
    四则运算2之小学二年级
    四则运算2--思路
    大道至简---读书随笔
    随机30道四则运算
    读书计划
    软件工程课堂作业(七)——电梯调度之需求规格说明书
    《梦断代码Dreaming In Code》阅读笔记(二)
    软件工程课堂作业(六)——结对开发(二)
    软件工程课堂作业(五)——终极版随机产生四则运算题目(C++)
  • 原文地址:https://www.cnblogs.com/csnd/p/12063235.html
Copyright © 2011-2022 走看看