• ZOJ 2314 带上下界的可行流


    对于无源汇问题,方法有两种.

    1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级汇,容量为x->y下界.建立有向边 x->y,容量为x->y的上界减下界.

    2 从点的角度来处理. 新建超级源汇,对于每个点流进的下界和为 in, 流出此点的下界和为out.如果in > out. 建立有向边 超级源->i,容量为in-out.反之,建立有向边 i->超级汇,容量为out-in.

    如果超级源的每一条出边都满流,则存在一个可行流,可行流的流量就是每一条逆向边的流量+ 此边下界.

    从点的角度的处理方法是边的处理方法的拓展.基于边的处理比较容易理解,但是复杂度较高.

    下面是基于点的处理的程序:

       1:  /*
       2:      带上下界的可行流
       3:  */
       4:  #include<iostream>
       5:  #include<cmath>
       6:  #include<memory>
       7:  #include <string.h>
       8:  #include <cstdio>
       9:  using namespace std;
      10:   
      11:  #define V 300      // vertex
      12:  #define E  40800     // edge
      13:  #define INF 0x3F3F3F3F  // 1061109567
      14:   
      15:  int i,j,k;
      16:  #define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
      17:  #define snuke(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
      18:   
      19:  struct MaxFlow
      20:  {
      21:      struct Edge
      22:      {
      23:          int v, w, next;     //w for capicity
      24:          int lb,up;
      25:      } edge[E];
      26:   
      27:      int head[V];          // head[u]表示顶点u第一条邻接边的序号, 若head[u] = -1, u没有邻接边
      28:      int e;                // the index of the edge
      29:      int src, sink;
      30:      int net[V];              // 流入此节点的流的下界和 - 流出此节点的流的下界和,对于带上下界的来进行使用
      31:   
      32:   
      33:      void addedge(int  u, int v, int w, int lb = 0, int up = INF, int rw = 0)
      34:      {
      35:          edge[e].v = v;
      36:          edge[e].w= w;
      37:          edge[e].next = head[u];
      38:          edge[e].lb = lb, edge[e].up = up;
      39:          head[u] = e++;
      40:          // reverse edge  v -> u
      41:          edge[e].v = u;
      42:          edge[e].w = rw;
      43:          edge[e].lb = lb, edge[e].up = up;
      44:          edge[e].next = head[v];
      45:          head[v] = e++;
      46:      }
      47:   
      48:      int ISAP(int VertexNum )
      49:      {
      50:          int u, v, max_flow, aug, min_lev;
      51:          int curedge[V], parent[V], level[V];
      52:          int count[V], augment[V];
      53:   
      54:          memset(level, 0, sizeof(level));
      55:          memset(count, 0, sizeof(count));
      56:          REP(i,VertexNum+1) curedge[i] = head[i];
      57:          max_flow = 0;
      58:          augment[src] = INF;
      59:          parent[src] = -1;
      60:          u = src;
      61:   
      62:          while (level[src] < VertexNum)
      63:          {
      64:              if (u == sink)
      65:              {
      66:                  max_flow += augment[sink];
      67:                  aug = augment[sink];
      68:                  for (v = parent[sink]; v != -1; v = parent[v])
      69:                  {
      70:                      i = curedge[v];
      71:                      edge[i].w  -= aug;
      72:                      edge[i^1].w  += aug;
      73:                      augment[edge[i].v] -= aug;
      74:                      if (edge[i].w == 0) u = v;
      75:                  }
      76:              }
      77:              for (i = curedge[u]; i != -1; i = edge[i].next)
      78:              {
      79:                  v = edge[i].v;
      80:                  if (edge[i].w > 0 && level[u] == (level[v]+1))
      81:                  {
      82:                      augment[v] = min(augment[u], edge[i].w);
      83:                      curedge[u] = i;
      84:                      parent[v] = u;
      85:                      u = v;
      86:                      break;
      87:                  }
      88:              }
      89:              if (i == -1)
      90:              {
      91:                  if (--count[level[u]] == 0) break;
      92:                  curedge[u] = head[u];
      93:                  min_lev = VertexNum;
      94:                  for (i = head[u]; i != -1; i = edge[i].next)
      95:                      if (edge[i].w > 0)
      96:                          min_lev = min(level[edge[i].v], min_lev);
      97:                  level[u] = min_lev + 1;
      98:                  count[level[u]]++;
      99:                  if (u != src ) u = parent[u];
     100:              }
     101:          }
     102:          return max_flow;
     103:      }
     104:      void solve()
     105:      {
     106:          int T; cin>>T;
     107:          for(int cas =1; cas <=T; cas++)
     108:          {
     109:              int N,M; cin>>N>>M;
     110:              e = 0;
     111:              memset(head, -1, sizeof(head));
     112:              memset(net, 0, sizeof(net));
     113:              int a,b,c,d;
     114:              for(int i=1; i<=M;i++)
     115:              {
     116:                  scanf("%d%d%d%d", &a, &b, &c, &d);
     117:                  net[b] += c; net[a] -= c;
     118:                  addedge(a,b,d-c, c,d);
     119:              }
     120:              // 无源汇,这两个是super src, super sink.
     121:              src =N+1; sink = N+2;
     122:              for(int i=1; i<=N; i++)
     123:              {
     124:                  if(net[i] > 0)
     125:                      addedge(src, i, net[i]);
     126:                  else
     127:                      addedge(i, sink, -net[i]);
     128:              }
     129:              ISAP(N+2);
     130:              bool flag = true;
     131:              for (i = head[src]; i != -1; i = edge[i].next)
     132:              {
     133:                  if(edge[i].w !=0)
     134:                  {
     135:                      flag = false;
     136:                      break;
     137:                  }
     138:              }
     139:              if(flag)
     140:              {
     141:                  cout<<"YES"<<endl;
     142:                  for(int i=0; i<M;i++)
     143:                  {
     144:                      cout<<edge[i*2+1].w + edge[i*2+1].lb<<endl;
     145:                  }
     146:                  cout<<endl;
     147:              }else
     148:              {
     149:                  cout<<"NO"<<endl;
     150:                  cout<<endl;
     151:              }
     152:          }
     153:   
     154:      }
     155:  }sap;
     156:   
     157:  int main()
     158:  {
     159:  //    freopen("1.txt","r",stdin);
     160:      sap.solve();
     161:      return 0;
     162:  }
  • 相关阅读:
    web 移动端 适配
    meta
    meta设置
    时间
    CentOS下配置nginx conf/koi-win为同一文件的各类错误
    CentOS7 配置LAMP
    centos 进度条卡死
    LeetCode02:两数相加
    LeetCode01:两数之和
    单链表类,链表逆置
  • 原文地址:https://www.cnblogs.com/sosi/p/3715737.html
Copyright © 2020-2023  润新知