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

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:  }

.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 2314 带上下界的可行流的更多相关文章

  1. HDU Destroy Transportation system(有上下界的可行流)

    前几天正看着网络流,也正研究着一个有上下界的网络流的问题,查看了很多博客,觉得下面这篇概括的还是相当精确的: http://blog.csdn.net/leolin_/article/details/ ...

  2. [ACdream 1211 Reactor Cooling]无源无汇有上下界的可行流

    题意:无源无汇有上下界的可行流 模型 思路:首先将所有边的容量设为上界减去下界,然后对一个点i,设i的所有入边的下界和为to[i],所有出边的下界和为from[i],令它们的差为dif[i]=to[i ...

  3. ZOJ 2314 有上下界的网络流

    problemCode=2314">点击打开链接 题意:给定m条边和n个节点.每条边最少的流量和最多的流量.保证每一个节点的出入流量和相等,问能够形成吗,能够则输出每条边的流量 思路: ...

  4. BZOJ2406矩阵——有上下界的可行流+二分答案

    题目描述 输入 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. 输出 第一行,输出最小的答案: 样例输入 2 2 0 1 2 1 0 1 样例输出 1 ...

  5. 【BZOJ2406】矩阵 二分+有上下界的可行流

    [BZOJ2406]矩阵 Description Input 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. Output 第一行,输出最小的答案: ...

  6. SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的可行流

    题目链接 题意:有向图中有n(1 <= n <= 200)个点,无自环或者环的节点个数至少为3.给定每条边的最小流量和最大流量,问每条边的可行流量为多少? 思路:一般求解的网络流并不考虑下 ...

  7. ZOJ 2314 Reactor Cooling | 无源汇可行流

    题目: 无源汇可行流例题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题解: 证明什么的就算了,下面给出一种建图方式 ...

  8. bzoj 2406 二分+有源有汇上下界网络流可行流判定

    弱爆了,典型的行列建模方式,居然想不到,题做少了,总结少了...... 二分答案mid s----------------------->i行-----------------------> ...

  9. sgu 194 上下界网络流可行流判定+输出可行流

    #include <cstdio> #include <cstring> #define min(a,b) ((a)<(b)?(a):(b)) #define oo 0x ...

随机推荐

  1. IOS 9 遇到的问题

    IOS9中通过url scheme调用其他app时候,控制台会输入 canOpenURL: failed for URL: "XXXXXX://" - error: "T ...

  2. 设置WinForm窗体及程序图标

    自己留着看,总是用的时候给忘记了,百度来百度去的麻烦. 设置 Ico 图标为 [资源文件] 项目名à右键à属性,在选项卡中选择"资源"   选择 "添加资源"à ...

  3. Windows SDK 之 Hook的使用

    在使用SetWindowsHookEx的过程中遇到的问题 函数原型 HHOOK WINAPI SetWindowsHookEx( _In_ int idHook, _In_ HOOKPROC lpfn ...

  4. Collection 和 Collections的区别。

    Collection 和 Collections的区别. Collections是个java.util下的类,它包含有各种有关集合操作的静态方法. Collection是个java.util下的接口, ...

  5. WCF之服务元数据

    服务元数据是用来获得服务的EndPoint的信息,也就是它的ABC. 服务有两种方案可以发布自己的元数据. 一种是基于HTTP-GET协议提供元数据: 一种是元数据交换方式,它往往使用一个专门的终结点 ...

  6. JavaScript 弹窗

    JavaScript 弹窗 可以在 JavaScript 中创建三种消息框:警告框.确认框.提示框. 警告框 警告框经常用于确保用户可以得到某些信息. 当警告框出现后,用户需要点击确定按钮才能继续进行 ...

  7. Codevs 1474 十进制转m进制

    时间限制: 1 s    空间限制: 128000 KB    题目等级 : 白银 Silver 题目描述 Description 将十进制数n转换成m进制数 m<=16 n<=100 输 ...

  8. 设计main函数退出后继续执行一段代码

    原理: 使用 _onexit() 函数注册一个函数,这个函数会在main函数退出后执行 使用原则: 1.包含在cstdlib中,是c语言中的库函数: 2.需要注册的函数格式为:int类型返回值.无参数 ...

  9. 《shell条件测试语句,字符串测试apache是否开启》

    还得我想了10分钟才明白”!=“和"-n"的用法区别,做个笔记捋一捋 第一种方法:测试apache是否开启?字符串测试 #!/bin/bash web=`/usr/bin/pgre ...

  10. java.lang.NoClassDefFoundError Adding a jar to an RCP application

    给RCP中加入jar包与一般的java工程是有些个区别的,否则会出现"java.lang.NoClassDefFoundError" Open plug-in.xmlGo to R ...