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

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2314

题目大意:

给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。

并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。

解题思路:

转自:https://www.cnblogs.com/WABoss/p/5371871.html

本质上就是求一个无源汇流量有上下界的容量网络的可行流,因为无源汇的容量网络上各个顶点都满足流量平衡条件,即所有点的∑流入流量=∑流出流量,可以看成里面的流是循环流动的,类似有向图欧拉回路。

而带上下界的网络可行流的求法,是根据网络流中一个流是可行流的充分必要条件——限制条件和平衡条件,去改造原网络,转化成不带下界的容量网络来求解的。数学模型那些证明之类的不难理解,见论文《一种简易的方法求解流量有上下界的网络中网络流问题》。

而改造的方式好像有两种挺流行的,我用的做法是:

  • 设d[u]为顶点u出边下界和-入边下界和,新建源点、汇点
  • 原网络的弧<u,v>容量设置成其上界-下界
  • 对于每一个顶点u,如果d[u]<0则源点向其连容量-d[u]的边,否则其向汇点连容量d[u]的边
  • 最后如果和源点相关的弧都满流则存在可行流,而各条边的流量+其在原网络的下界就是一个解

代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<vector>
  8 #define LL long long
  9 #define pii pair<int,int>
 10 #define pll pair<long long,long long>
 11 #define rep(i,a,b) for(int i=a;i<=b;i++)
 12 #define per(i,a,b) for(int i=a;i>=b;i--)
 13 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
 14 #define bug cout<<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"<<endl;
 15 #define bugc(_) cout << (#_) << " = " << (_) << endl;
 16 using namespace std;
 17 const int N=2e2+5;
 18 const int M=4e4+5;
 19 const int INF=0x3f3f3f3f;
 20
 21 struct node{
 22     int to,next,flow;
 23 }edge[M*2];
 24
 25 int cnt,st,en;
 26 int head[N],dep[N],d[N],low[M];//d[u]为顶点u出边下界和-入边下界和,low[i]记录第i条边的下界
 27
 28 void init(){
 29     cnt=2;
 30     memset(head,0,sizeof(head));
 31     memset(d,0,sizeof(d));
 32 }
 33
 34 void link(int u,int v,int flow){
 35     edge[cnt]=node{v,head[u],flow};
 36     head[u]=cnt++;
 37     edge[cnt]=node{u,head[v],0};
 38     head[v]=cnt++;
 39 }
 40
 41 int bfs(){
 42     memset(dep,0,sizeof(dep));
 43     dep[st]=1;
 44     queue<int>q;
 45     q.push(st);
 46     while(!q.empty()){
 47         int u=q.front();
 48         q.pop();
 49         for(int i=head[u];i;i=edge[i].next){
 50             node t=edge[i];
 51             if(t.flow&&!dep[t.to]){
 52                 dep[t.to]=dep[u]+1;
 53                 q.push(t.to);
 54             }
 55         }
 56     }
 57     return dep[en];
 58 }
 59
 60 int dfs(int u,int fl){
 61     if(en==u) return fl;
 62     int tmp=0;
 63     for(int i=head[u];i&&fl;i=edge[i].next){
 64         node &t=edge[i];
 65         if(t.flow&&dep[t.to]==dep[u]+1){
 66             int x=dfs(t.to,min(t.flow,fl));
 67             if(x>0){
 68                 tmp+=x;
 69                 fl-=x;
 70                 t.flow-=x;
 71                 edge[i^1].flow+=x;
 72             }
 73         }
 74     }
 75     if(!tmp) dep[u]=-2;
 76     return tmp;
 77 }
 78
 79 int dinic(){
 80     int ans=0;
 81     while(bfs()){
 82         while(int d=dfs(st,INF))
 83             ans+=d;
 84     }
 85     return ans;
 86 }
 87
 88 int main(){
 89     int T;
 90     scanf("%d",&T);
 91     while(T--){
 92         int n,m;
 93         scanf("%d%d",&n,&m);
 94         init();
 95         st=0,en=n+1;
 96         for(int i=1;i<=m;i++){
 97             int u,v,c;
 98             scanf("%d%d%d%d",&u,&v,&low[i],&c);
 99             link(u,v,c-low[i]);
100             d[u]+=low[i];
101             d[v]-=low[i];
102         }
103         int sum=0;
104         for(int i=1;i<=n;i++){
105             if(d[i]<0) link(st,i,-d[i]);
106             else{
107                 sum+=d[i];
108                 link(i,en,d[i]);
109             }
110         }
111         if(sum!=dinic()) puts("NO");
112         else{
113             puts("YES");
114             for(int i=2;i<=2*m;i+=2){
115                 printf("%d\n",edge[i^1].flow+low[i>>1]);
116             }
117         }
118         puts("");
119     }
120     return 0;
121 }

原文地址:https://www.cnblogs.com/fu3638/p/9892416.html

时间: 2024-10-24 21:46:24

ZOJ 2314 Reactor Cooling(无源汇有上下界可行流)的相关文章

ZOJ 2314 Reactor Cooling 无源汇有上下界网络流

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题意:给出N个点,M条边的有向图,每条边的有上下界规定,问是否存在一个可行流满足条件,如果满足输出YES并输出每条边的流量. 如果不满足输出NO. 根据周源的<一种简易的方法求解流量有上下界的网络中网络流问题> 无源汇上下界网络流的做法是: 设边u->v的下界是B(u,v),上界是C(u,v). 设M(i)为对于i结点的流入i的下界总和-流出i的下界总

ZOJ2314 Reactor Cooling 无源汇有上下界最大流

推荐看这里 #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; int n, m, uu, vv, ww, cc, hea[225], cnt, ss, tt, maxFlow, lev[225], tot, T; const int oo=0x3f3f3f3f; struct Edge{ int too, nxt, ca

无源汇有上下界可行流存在定理

H - Reactor Cooling Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuclear reactor to produce plutonium

[loj#115] 无源汇有上下界可行流 网络流

#115. 无源汇有上下界可行流 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 这是一道模板题. n nn 个点,m mm 条边,每条边 e ee 有一个流量下界 lower(e) \text{lower}(e)lower(e) 和流量上界 upper(e) \text{upper}(e)upper(e),求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限

LOJ #115. 无源汇有上下界可行流

#115. 无源汇有上下界可行流 描述 这是一道模板题. n n n 个点,m m m 条边,每条边 e e e 有一个流量下界 lower(e) \text{lower}(e) lower(e) 和流量上界 upper(e) \text{upper}(e) upper(e),求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制. 输入格式 第一行两个正整数 n n n.m m m. 之后的 m m m 行,每行四个整数 s s s.t t t.lower \text{lowe

SGU 194. Reactor Cooling(无源汇有上下界的网络流)

时间限制:0.5s 空间限制:6M 题意: 显然就是求一个无源汇有上下界的网络流的可行流的问题 Solution: 没什么好说的,直接判定可行流,输出就好了 code /* 无汇源有上下界的网络流 */ #include <iostream> #include <cstring> #define ms(a,b) memset(a,b,sizeof a) using namespace std; const int MAXN = 209; struct node { int u, v

(一道模板题) 无源汇有上下界可行流

题目描述 这是一道模板题. n 个点,m  条边,每条边 e  有一个流量下界 lower(e) 和流量上界 upper(e),求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制. 输入格式 第一行两个正整数 n .m . 之后的 m 行,每行四个整数 s .t .lower .upper. 输出格式 如果无解,输出一行 NO. 否则第一行输出 YES,之后 m  行每行一个整数,表示每条边的流量. 样例 样例输入 1 4 6 1 2 1 2 2 3 1 2 3 4 1 2

sgu194 Reactor Cooling【无源汇有上下界可行流】

这是模板题了吧,先建立附加源汇,然后保留每个点的in-out,如果这个值是正的,那么就从附加源先这个点连一个边权为in-out的边,否则从这个点向附加汇连一条相反数的边,剩下题目中的边就用上界-下界连就好了. 1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #def

hdu 4940 无源汇有上下界最大流

题意:给出一个有向强连通图,每条边有两个值分别是破坏该边的代价和把该边建成无向边的代价(建立无向边的前提是删除该边)问是否存在一个集合S,和一个集合的补集T,破坏所有S集合到T集合的边代价和是X,然后修复T到S的边为无向边代价和是Y,满足Y<X:满足输出unhappy,否则输出happy:</span> <span style="font-family: Arial, Helvetica, sans-serif;">分析:无源汇有上下界可行流判定, 原来每