zoukankan      html  css  js  c++  java
  • ZOJ 3229 有上下界最大流

       1:  /**
       2:      ZOJ 3229 有上下界的最大流
       3:      两次求最大流的过程,非二分
       4:      有源汇上下界的最大流问题, 首先连接 sink -> src, [0,INF].
       5:      根据net的正负,来建立 Supersrc 与 supersink 之间的边,做一次 maxflow.
       6:      若所有的Supersrc 与 Supersink满流,则说明存在可行流.
       7:      然后删除 sink -> src之间的边.(cap 置零即可). 从src -> sink 做一次最大流.
       8:      两次最大流的和即为整个网络的最大流.
       9:  */
      10:   
      11:  #include<iostream>
      12:  #include<cmath>
      13:  #include<memory>
      14:  #include <string.h>
      15:  #include <cstdio>
      16:  #include <vector>
      17:  using namespace std;
      18:   
      19:  #define V 1500      // vertex
      20:  #define E  V *80     // edge
      21:  #define INF 0x3F3F3F3F  // 1061109567
      22:   
      23:  int i,j,k;
      24:  #define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
      25:  #define snuke(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
      26:   
      27:  struct MaxFlow
      28:  {
      29:      struct Edge
      30:      {
      31:          int v, w, next;     //w for capicity
      32:          int lb,up;
      33:      } edge[E];
      34:   
      35:      int head[V];          // head[u]表示顶点u第一条邻接边的序号, 若head[u] = -1, u没有邻接边
      36:      int e;                // the index of the edge
      37:      int src, sink;
      38:      int net[V];              // 流入此节点的流的下界和 - 流出此节点的流的下界和,对于带上下界的来进行使用
      39:   
      40:   
      41:      void addedge(int  u, int v, int w, int lb = 0, int up = INF, int rw = 0)
      42:      {
      43:          edge[e].v = v;
      44:          edge[e].w= w;
      45:          edge[e].next = head[u];
      46:          edge[e].lb = lb, edge[e].up = up;
      47:          head[u] = e++;
      48:          // reverse edge  v -> u
      49:          edge[e].v = u;
      50:          edge[e].w = rw;
      51:          edge[e].lb = lb, edge[e].up = up;
      52:          edge[e].next = head[v];
      53:          head[v] = e++;
      54:      }
      55:   
      56:      int ISAP(int VertexNum )
      57:      {
      58:          int u, v, max_flow, aug, min_lev;
      59:          int curedge[V], parent[V], level[V];
      60:          int count[V], augment[V];
      61:   
      62:          memset(level, 0, sizeof(level));
      63:          memset(count, 0, sizeof(count));
      64:          REP(i,VertexNum+1) curedge[i] = head[i];
      65:          max_flow = 0;
      66:          augment[src] = INF;
      67:          parent[src] = -1;
      68:          u = src;
      69:   
      70:          while (level[src] < VertexNum)
      71:          {
      72:              if (u == sink)
      73:              {
      74:                  max_flow += augment[sink];
      75:                  aug = augment[sink];
      76:                  for (v = parent[sink]; v != -1; v = parent[v])
      77:                  {
      78:                      i = curedge[v];
      79:                      edge[i].w  -= aug;
      80:                      edge[i^1].w  += aug;
      81:                      augment[edge[i].v] -= aug;
      82:                      if (edge[i].w == 0) u = v;
      83:                  }
      84:              }
      85:              for (i = curedge[u]; i != -1; i = edge[i].next)
      86:              {
      87:                  v = edge[i].v;
      88:                  if (edge[i].w > 0 && level[u] == (level[v]+1))
      89:                  {
      90:                      augment[v] = min(augment[u], edge[i].w);
      91:                      curedge[u] = i;
      92:                      parent[v] = u;
      93:                      u = v;
      94:                      break;
      95:                  }
      96:              }
      97:              if (i == -1)
      98:              {
      99:                  if (--count[level[u]] == 0) break;
     100:                  curedge[u] = head[u];
     101:                  min_lev = VertexNum;
     102:                  for (i = head[u]; i != -1; i = edge[i].next)
     103:                      if (edge[i].w > 0)
     104:                          min_lev = min(level[edge[i].v], min_lev);
     105:                  level[u] = min_lev + 1;
     106:                  count[level[u]]++;
     107:                  if (u != src ) u = parent[u];
     108:              }
     109:          }
     110:          return max_flow;
     111:      }
     112:      // girl 0-m-1, day m,m+n-1, src m+n, sink m+n+1. all m+n+2 point
     113:      void solve()
     114:      {
     115:          int N,M; // n days m girl
     116:          while(scanf("%d%d", &N,&M) != EOF)
     117:          {
     118:              e = 0;
     119:              memset(head, -1, sizeof(head));
     120:              memset(net, 0, sizeof(net));
     121:              int G; src = M+N, sink = M+N+1;
     122:              for(int i=0; i<M; i++)
     123:              {
     124:                  scanf("%d", &G);
     125:                  addedge(i,sink,INF-G, G,INF);
     126:                  net[i] -= G;
     127:                  net[sink] += G;
     128:              }
     129:              vector<int> CE;
     130:              for(int i=0; i<N; i++)
     131:              {
     132:                  int C,D; scanf("%d%d", &C,&D);
     133:                  addedge(src, M+i, D, 0, D);
     134:                  for(int j=0; j<C; j++)
     135:                  {
     136:                      int T,L,R; scanf("%d%d%d", &T,&L,&R);
     137:                      CE.push_back(e);
     138:                      addedge(M+i,T,R-L, L,R);
     139:                      net[M+i] -= L;
     140:                      net[T] += L;
     141:                  }
     142:              }
     143:              int spec = e;
     144:              // 添加从sink -> src 容量为INF的边
     145:              addedge(sink, src, INF,0,INF);
     146:              src = M+N+2; sink = M+N+3;  // M+N+4 point
     147:              int rangea = e;
     148:              for(int i=0; i<M+N+2; i++)
     149:              {
     150:                  if(net[i] >= 0) addedge(src, i, net[i]);
     151:                  else  addedge(i, sink,-net[i]);
     152:              }
     153:              double ret = 0;
     154:              int rangeb = e;
     155:              // 从super src ->super sink 做一次最大流
     156:              ret+=ISAP(M+N+4);
     157:              bool flag = true;
     158:              // 判断是否满流
     159:              for(int i= rangea; i<rangeb; i+=2)
     160:              {
     161:                  if(edge[i].w !=0)
     162:                  {
     163:                      flag = false;
     164:                      break;
     165:                  }
     166:              }
     167:              if(flag)
     168:              {
     169:                  // 修改 src sink,然后把 从sink -> src 的边删除
     170:                  src = M+N; sink = M+N+1;
     171:                  edge[spec].w = 0; edge[spec+1].w = 0;
     172:                  // 从 src->sink 做一次最大流
     173:                  ret += ISAP(M+N+2);
     174:                  int tmp = ret;
     175:                  printf("%d
    ", tmp);
     176:                  for(int i=0; i<CE.size(); i++)
     177:                      printf("%d
    ", edge[CE[i]+1].lb + edge[CE[i]+1].w);
     178:              }else printf("-1
    ");
     179:              cout<<endl;
     180:          }
     181:      }
     182:  }sap;
     183:   
     184:  int main()
     185:  {
     186:  //    freopen("1.txt","r",stdin);
     187:      sap.solve();
     188:      return 0;
     189:  }
  • 相关阅读:
    Redis21:客户端与服务器端的通信与redis管道
    Redis20:keys、scan、bigkeys、查看key的存储方式
    Redis19:限流
    Redis18:分布式锁
    Redis17:cluster集群
    Redis16:两种redis集群解决方案:codis和cluster
    Android : 获取声卡信息的测试代码
    Android : 基于alsa库的音乐播放
    Android system :灯光系统_HAL_lights
    Android system :led_class驱动
  • 原文地址:https://www.cnblogs.com/sosi/p/3716721.html
Copyright © 2011-2022 走看看