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\n", tmp);
 176:                  for(int i=0; i<CE.size(); i++)
 177:                      printf("%d\n", edge[CE[i]+1].lb + edge[CE[i]+1].w);
 178:              }else printf("-1\n");
 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:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

ZOJ 3229 有上下界最大流,布布扣,bubuko.com

时间: 2024-11-07 12:05:19

ZOJ 3229 有上下界最大流的相关文章

zoj 3231(上下界费用流)

题意:树上每个节点上有若干苹果,边上带权,问你最小费用使得书上的苹果方差最小. 思路:上下费用流问题,参考http://blog.csdn.net/qq564690377/article/details/8870587 代码如下: 1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last m

ZOJ 3229 有上下界的有汇源的最大流

点击打开链接 题意:有n天和m个女孩,每天我可以收集女孩的照片(单身狗来袭),但每天我最多可以收集D个照片,而且对于i好女孩,我这天最少收集L张照片,最多R张照片,并且每个女孩的照片至少要G[i]张,问能否收集成功,成功则输出每天每个女孩的收集量 思路:昨天看了看上下界的题目,感觉还是蛮好理解的,今天哪这题开刀,本弱做了快一个下午才做出来,发现建图有个地方建错了,调了半天bug........有源汇的上下界网络流需要先转化为无源汇的在进行下一步,那就连边把,一共n天,那么源点0连到天上去,流量为

[zoj] 3229 Shoot the Bullet || 有源汇上下界最大流

zoj 文文要给幻想乡的女孩子们拍照,一共n天,m个女孩子,每天文文至多拍D[i]张照片,每个女孩子总共要被文文至少拍G[i]次.在第i天,文文可以拍c[i]个女孩子,c[i]个女孩子中每个女孩子在当天被拍的次数是[l,r],求最多可以拍多少张照片,以及每天每个可以拍的女孩子被拍了多少张照片. 有源汇上下界最大流. 先跑有源汇上下界可行流,判断是否可行,若可行则此时跑原图中s到t的最大流即为答案. //代码与题解不符-- #include<cstdio> #include<algorit

zoj 3229 Shoot the Bullet(有源汇上下界最大流)

Shoot the Bullethttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia

ZOJ 3229 Shoot the Bullet 无源汇上下界最大流

Shoot the Bullet Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia where humans and other beings such as fairies, youkai(phantoms)

zoj 2314 Reactor Cooling (无源汇上下界可行流)

Reactor Coolinghttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuclear re

POJ2396&amp;ZOJ1994--Budget【有源汇上下界可行流】

链接:http://poj.org/problem?id=2396 题意:给一个n*m的矩阵,给出每行的总和以及每列的总和,再给出某些位置的最小或最大限制,问是否存在可能的矩阵,如果存在输出一种矩阵信息. 思路:这是一个有源汇的上下界可行流,对于这种题,从汇点连一条弧到源点,容量为INF,这不会影响流量平衡条件,并且此时原图转换为了无源汇的上下界可行流,剩下的做法和无源汇一样. 建图:原图源点src连向每个行顶点,容量为每行的和,每个列顶点连向汇点,容量为每个列顶点的和,行顶点和列顶点间也各有一

有上下界的网络流3-有源汇带上下界最小流SGU176

题目大意:有一个类似于工业加工生产的机器,起点为1终点为n,中间生产环节有货物加工数量限制,输入u v z c, 当c等于1时表示这个加工的环节必须对纽带上的货物全部加工(即上下界都为z),c等于0表示加工上界限制为z,下界为0,求节点1(起点)最少需要投放多少货物才能传送带正常工作. 解题思路:    1.直接 增设超级源点ss和超级汇点tt并连上附加边,对 当前图 求 无源汇带上下界可行流    2.将图的汇点sd连一条容量无限制的边到图的源点st,再求一遍 无源汇带上下界可行流    3.

POJ 3801 有上下界最小流

1: /** 2: POJ 3801 有上下界的最小流 3: 4: 1.对supersrc到supersink 求一次最大流,记为f1.(在有源汇的情况下,先使整个网络趋向必须边尽量满足的情况) 5: 2.添加一条边sink -> src,流量上限为INF,这条边记为p.(构造无源汇网络) 6: 3.对supersrc到supersink再次求最大流,记为f2,这里判断是否为可行流.(要判断可行,必须先构造无源汇网络流,因此要再次求最大流) 7: 8: 此网络流的最小流即为 sink -> s