有上下界的网络流1-无源汇带上下界网络流SGU194

今天开始啃网络流了。对于求解无源汇带上下界的网络流,我们可以这样建图:
建图模型: 
        以前写的最大流默认的下界为0,而这里的下界却不为0,所以我们要进行再构造让每条边的下界为0,这样做是为了方便处理。对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low。可是这样做了的话流量就不守恒了,为了再次满足流量守恒,即每个节点"入流=出流”,我们增设一个超级源点st和一个超级终点sd。我们开设一个数组du[]来记录每个节点的流量情况。

du[i]=in[i](i节点所有入流下界之和)-out[i](i节点所有出流下界之和)。

当du[i]大于0的时候,st到i连一条流量为du[i]的边。

当du[i]小于0的时候,i到sd连一条流量为-du[i]的边。

最后对(st,sd)求一次最大流即可,当所有附加边全部满流时,有可行解。
(我们默认了图中每条边已经有了最小的流量,可是现在的图中的点 入流不等于出流,于是我们通过附加边使得:
       1. 超级源点 连接到 入流大于出流的点,以增大该点的出流,使实际流量平衡(实际流量为最小流量+当前流量,并且不算超级源点和汇点的流量)。
       2.出流大于入流的点 连接到 超级汇点,以增大该点的入流(因为该点可以把流量全部排到超级汇点,所以可以有跟多的流量流入该点),使实际流量平衡。

注意:无源汇带上下界的网络流中 求出来的网络流是个循环体,即虽然没有源点汇点但内部的点都保持流量守恒。
            且该算法仅能求出一个可行解,最终得到的网络流并不能保证是最大流。

SGU194题目大意:
给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。
今晚RP不错,一遍就AC。
下面是我的代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 #include<cstring>
 8 #define maxn 0x7fffffff
 9 using namespace std;
10 struct edge{int to,cap,rev,num;};
11 int flow[100000],ch[250],du[250];
12 vector <edge> E[250];
13 int st,sd,n,m;
14 void Add_Edge(int from,int to,int cap,int num){
15      edge t;t.num=num*2;
16      t.to=to,t.cap=cap,t.rev=E[to].size();
17      E[from].push_back(t);
18      t.num=num*2+1;
19      t.to=from,t.cap=0,t.rev=E[from].size()-1;
20      E[to].push_back(t);
21 }
22 bool bfs(){
23      queue <int> que;
24      memset(ch,-1,sizeof(ch));
25      ch[st]=0;que.push(st);
26      while(que.size()){
27                      int t=que.front();que.pop();
28                      for(int i=0;i<E[t].size();i++){
29                              if(E[t][i].cap && ch[E[t][i].to]<0) {
30                                             ch[E[t][i].to]=ch[t] + 1;
31                                             que.push(E[t][i].to);
32                              }
33                      }
34      }
35      return (ch[sd]>-1);
36 }
37 int dfs(int v,int f){
38      int r=0;
39      if(v==sd) return f;
40      for(int i=0;i<E[v].size();i++){
41              if(f==0) return r;
42              edge &t=E[v][i];
43              if(ch[t.to]==ch[v]+1 && t.cap>0) {
44                                   int u=dfs(t.to,min(t.cap,f));
45                                   t.cap-=u;E[t.to][t.rev].cap+=u;
46                                   f-=u;r+=u;
47              }
48      }
49      return r;
50 }
51 int dinic(){
52     int flow_sum=0;
53     while(bfs())  flow_sum+=dfs(st,maxn);
54     return flow_sum;
55 }
56
57 int main(){
58     int a,b,maxx,minn;
59     scanf("%d%d",&n,&m);
60     for(int i=0;i<m;i++){
61             scanf("%d%d%d%d",&a,&b,&minn,&maxx);
62             flow[i+1]=minn;
63             du[a]-=minn;du[b]+=minn;
64             Add_Edge(a,b,maxx-minn,i+1);
65     }
66     st=0;sd=n+1;
67     for(int i=1;i<=n;i++){
68             if(du[i]>0)  Add_Edge(st,i,du[i],0);
69             if(du[i]<0)  Add_Edge(i,sd,-du[i],0);
70     }
71     dinic();
72     bool flag=true;
73     for(int i=st;i<=sd;i++){
74             for(int j=0;j<E[i].size();j++){
75                     int k=E[i][j].num;
76                     if(k%2==1){
77                                k=k/2;
78                                if(1<=k && k<=m) flow[k]+=E[i][j].cap;
79                     }
80                     else{
81                          if(k==0 && E[i][j].cap>0) flag=false;
82                     }
83
84             }
85     }
86     if(flag){
87              printf("YES\n");
88              for(int i=1;i<=m;i++) printf("%d\n",flow[i]);
89     }
90     else{
91          printf("NO\n");
92     }
93     return 0;
94 }
时间: 2024-08-04 17:33:52

有上下界的网络流1-无源汇带上下界网络流SGU194的相关文章

有上下界的网络流2-有源汇带上下界网络流ZOJ3229

ZOJ3229题目大意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝可以和C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照:否则输出-1. 解题思路:        1.增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为正无穷的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边.        2.

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

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

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

[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),求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限

【HDU 4940】Destroy Transportation system(数据水/无源无汇带上下界可行流)

Description Tom is a commander, his task is destroying his enemy’s transportation system. Let’s represent his enemy’s transportation system as a simple directed graph G with n nodes and m edges. Each node is a city and each directed edge is a directe

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

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

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

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. 无源汇有上下界可行流 描述 这是一道模板题. 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

有源汇带上下界最小流

LOj 模板 思路我就不多说了吧,和有源汇带上下界最大流一样,只不过这次是初流-残流网络最大流.关键这个模板题写的过程无限T一组,让我很绝望.在网上搜罗了很多代码,发现我有些地方可以优化. (1)跑dinic的时候可以使用当前弧优化 (2)在dinic过程中,如果rest已经等于0了,直接返回.不要不管他,感觉没什么影响,其实有的数据会卡死的(千万在边权更新之后再返回). #include<iostream> #include<cstdio> #include<cstring