网络流入门3——有上下界的最大流

如果流网络中每条边e对应两个数字B(e)和C(e),分别表示该边上的流量至少要是B(e),最多C(e),

那么,在这样的流网络上求最大流,就是有上下界的最大流问题。 
这种网络不一定存在可行流
 
?思路:将下界“分离”出去, 使问题转换为下界为0的普通网络流问题
 将原弧(u,v)分离出一条必要弧: 
 由于必要弧的有一定要满流的限制,将必要弧“拉”出来集中考虑: 
添加附加点x,y。想像一条不限上界的(x, y),用必要弧将它们“串”起来,
即对于有向必要弧(u, v),添加(u, x),(y, v),容量为必要弧容量。
这样就建立了一个等价的网络。
去掉边(x,y),添加由t到s的容量为正无穷大的边,使y和x分别成为新的源和新的汇。 
  
若此图上的最大流能够占满与Y相连的所有边的容量(自然也就会占满所有连到x的边的容量),


那么原图上就存在满足上下界条件的可行流  




对原图上的满足上下界条件的可行流进行增广,直到找到最大流。


增广的过程中,对于必要弧不能退流(添加反向边)。 

1.无源汇上下界最大流:

194. Reactor Cooling
time limit per test: 0.5 sec.
memory limit per test: 65536 KB
input: standard
output: standard



The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuclear reactor to produce plutonium for the nuclear bomb they are planning to create. Being the wicked computer genius of this group, you are responsible for developing the cooling system for the reactor. 

The cooling system of the reactor consists of the number of pipes that special cooling liquid flows by. Pipes are connected at special points, called nodes, each pipe has the starting node and the end point. The liquid must flow by the pipe from its start point to its end point and not in the opposite direction. 

Let the nodes be numbered from 1 to N. The cooling system must be designed so that the liquid is circulating by the pipes and the amount of the liquid coming to each node (in the unit of time) is equal to the amount of liquid leaving the node. That is, if we designate the amount of liquid going by the pipe from i-th node to j-th as f ij, (put f ij = 0 if there is no pipe from node i to node j), for each i the following condition must hold: 


sum(j=1..N, f ij) = sum(j=1..N, f ji


Each pipe has some finite capacity, therefore for each i and j connected by the pipe must be f ij ≤ c ij where c ij is the capacity of the pipe. To provide sufficient cooling, the amount of the liquid flowing by the pipe going from i-th to j-th nodes must be at least l ij, thus it must be f ij ≥ l ij

Given c ij and l ij for all pipes, find the amount f ij, satisfying the conditions specified above. 

Input

The first line of the input file contains the number N (1 ≤ N ≤ 200) - the number of nodes and and M — the number of pipes. The following M lines contain four integer number each - i, j, l ij and c ij each. There is at most one pipe connecting any two nodes and 0 ≤ l ij ≤ c ij ≤ 10 5 for all pipes. No pipe connects a node to itself. If there is a pipe from i-th node to j-th, there is no pipe from j-th node to i-th. 

Output

On the first line of the output file print YES if there is the way to carry out reactor cooling and NO if there is none. In the first case M integers must follow, k-th number being the amount of liquid flowing by the k-th pipe. Pipes are numbered as they are given in the input file. 

Sample test(s)

Input
 
Test #1 
4 6 
1 2 1 2 
2 3 1 2 
3 4 1 2 
4 1 1 2 
1 3 1 2 
4 2 1 2 
Test #2 
4 6 
1 2  1 3 
2 3  1 3 
3 4  1 3 
4 1  1 3 
1 3  1 3 
4 2 1 3 
Output
 
Test #1 

NO 

Test #2 

YES 






题目大意:给出n个节点和m条管子,每根管子都是用来流液体的,连接管子短点的叫节点,水管的流向是单项的,没有管子会只连接着一个节点,也就是说管子连成环状图,构成液体循环制冷系统,保证每个节点的流入量=流出量,每根管子都有其最大流通量Cij,为了保证制冷效果每根管子都有一定的流量下限Lij,即

Lij<=Fij<=Cij,求出每根管子的实际流量Fij,要求满足条件,如果不存在则输出NO;

分析:无源汇点网络流模型:

问题模型:

给定一个加权的有向图,满足:

(1)容量限制条件:

(2)流量平衡条件:

(2)中的即除了源汇外,所有点都满足流量平衡条件,则称G有源汇网络;否则,即不存在源汇,所有点都满足流量平衡条件,则称G无源汇网络。

将这类问题由易到难一一解决:

问题[1] 求无源汇的网络有上下界的可行流

由于下界是一条弧上的流必需要满足的确定值。下面引入必要弧的概念:必要弧是一定流要满的弧。必要弧的构造,将容量下界的限制分离开了,从而构造了一个没有下界的网络G’:

1. 将原弧(u,v)分离出一条必要弧:。(红色表示)

2. 原弧:


由于必要弧的有一定要满的限制,将必要弧“拉”出来集中考虑:


添加附加源x, 附加汇y。想像一条不限上界的(y, x),用必要弧将它们“串”起来,即对于有向必要弧(u, v),添加(u, y)(x, v),容量为必要弧容量。这样就建立了一个等价的网络。


一个无源汇网络的可行流的方案一定是必要弧是满的。若去掉(y, x)后,附加源x到附加汇y的最大流,能使得x的出弧或者y的入弧都满,充要于原图有可行流。


算法:

1. 按上述方法构造新网络(分离必要弧,附加源汇)

2. 求附加源x到附加汇y的最大流

3. 若x的出弧或y的入弧都满,则有解,将必要弧合并回原图;否则,无解。

4.  根据其残留网络,对每条管子的剩余,最大容量Cij-残余ij就是当前管子的实际流量。
代码:

#include"stdio.h"
#include"string.h"
#include"queue"
#define M 222
#define inf 100000000
using namespace std;
struct node
{
    int u,v,w,c,next;
}edge[M*M*3];
int t,head[M],work[M],dis[M];
void init()
{
    t=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w,int c)
{
    edge[t].u=u;
    edge[t].v=v;
    edge[t].w=w;
    edge[t].c=c;
    edge[t].next=head[u];
    head[u]=t++;

    edge[t].u=v;
    edge[t].v=u;
    edge[t].w=0;
    edge[t].c=c;
    edge[t].next=head[v];
    head[v]=t++;
}
int bfs(int source,int sink)
{
    memset(dis,-1,sizeof(dis));
    queue<int>q;
    q.push(source);
    dis[source]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(edge[i].w&&dis[v]==-1)
            {
                dis[v]=dis[u]+1;
                q.push(v);
                if(v==sink)
                    return 1;
            }
        }
    }
    return 0;
}
int dfs(int cur,int a,int sink)
{
    if(cur==sink)return a;
    for(int &i=work[cur];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(edge[i].w&&dis[v]==dis[cur]+1)
        {
            int tt=dfs(v,min(a,edge[i].w),sink);
            if(tt)
            {
                edge[i].w-=tt;
                edge[i^1].w+=tt;
                return tt;
            }
        }
    }
    return 0;
}
int Dinic(int start,int sink)
{
    int ans=0;
    while(bfs(start,sink))
    {
        memcpy(work,head,sizeof(head));
        while(int tt=dfs(start,inf,sink))
            ans+=tt;
    }
    return ans;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        init();
        int source=0;
        int sink=n+1;
        int sum=0;
        while(m--)
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            add(a,b,d-c,d);//对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low
            add(source,b,c,d);//可是这样做了的话流量就不守恒了,为了再次满足流量守恒,
            add(a,sink,c,d);//即每个节点"入流=出流”,我们增设一个超级源点source和一个超级终点sink
            sum+=c;
        }
        int ans=Dinic(source,sink);
        if(ans<sum)
            printf("NO\n");
        else
        {
            printf("YES\n");
            for(int i=0;i<t;i+=6)
                printf("%d\n",edge[i].c-edge[i].w);
        }
    }
    return 0;
}

参考:http://blog.csdn.net/mypsq/article/details/38467727

Again

问题模型:

给定一个加权的有向图,满足:

(1)容量限制条件:

              

(2)流量平衡条件:

             

(2)中的即除了源汇外,所有点都满足流量平衡条件,则称G有源汇网络;否则,即不存在源汇,所有点都满足流量平衡条件,则称G无源汇网络。

将这类问题由易到难一一解决:

问题[1] 求无源汇的网络有上下界的可行流

由于下界是一条弧上的流必需要满足的确定值。下面引入必要弧的概念:必要弧是一定流要满的弧。必要弧的构造,将容量下界的限制分离开了,从而构造了一个没有下界的网络G

1 将原弧(u,v)分离出一条必要弧:。(红色表示)

2 原弧:

由于必要弧的有一定要满的限制,将必要弧出来集中考虑:

添加附加源x, 附加汇y。想像一条不限上界的(y, x),用必要弧将它们“串”起来,即对于有向必要弧(u, v),添加(u, y)(x, v),容量为必要弧容量。这样就建立了一个等价的网络。

一个无源汇网络的可行流的方案一定是必要弧是满的。若去掉(y, x)后,附加源x到附加汇y的最大流,能使得x的出弧或者y的入弧都满,充要于原图有可行流。

算法:

1. 按上述方法构造新网络(分离必要弧,附加源汇)

2. 求附加源x到附加汇y的最大流

3. x的出弧或y的入弧都满,则有解,将必要弧合并回原图;否则,无解。

问题[2] 求有源汇的网络有上下界的可行流

加入边(t, s),下界为0(保证不会连上附加源汇x, y),不限上界,将问题[2]转化为问题[1]来求解。

问题[3]求有源汇的网络有上下界的最大流

算法:

1. 先转化为问题[2]来求解一个可行流。若可行无解,则退出。由于必要弧是分离出来的,所以就可以把必要弧(附加源汇及其临边)及其上的流,暂时删去。再将(T,S)删去,恢复源汇。

2. 再次,从ST找增广轨,求最大流。

3. 最后将暂时删去的下界信息恢复,合并到当前图中。输出解。

这样既不破坏下界(分离出来)也不超出上界(2步满足容量限制),问题解决。

问题[4]求有源汇的网络有上下界的最小流

算法:

1. 同问题[3]

2. TS找增广轨,不断反着改进。

3. 同问题[3]

问题[3]与问题[4]的另一种简易求法:

注意问题[2]中,构造出的(t, s),上下界几乎没什么限制。下面看看它的性质:

定理:如果从st有一个流量为a的可行流f,那么从ts连一条弧(t, s),其流量下界b(t, s) = a,则这个图一定有一个无源汇的可行流:除了弧(t, s)的容量为a外,其余边的容量与f相同。

证明:如果从st的最大流量为amax,那么从ts连一条下界b(t, s) = a’ > amax的弧(t, s),则从在这个改造后的图中一定没有无源汇的可行流:否则将这个可行流中的弧(t, s)除去,就得到了原图中st的流量为a’的流,大于最大流量amax,产生矛盾。

可以二分枚举这个参数a,即下界b(t, s),每次用问题[1]判断是否有可行流。这样就可以求出最大流。

同理,问题[4]要求最小流,只要二分枚举上界c(t, s)即可。

因为朴素的预流推进算法O(N3),总复杂度为O(N3 log2流量

思路:

无源汇 (附加源汇+最大解决)

有源汇 (附加(T,S)->无源汇)

根据这个讲解自己写一个相应的程序就可以了。。。这个题里面。。把每一行看成一个点。。每一列看成一个点来建图。。。。(IMPOSSIBLE少写一个s wa了半天。。挥泪呀。。。。TT。。。)

还有就是网上的上下界的网络流之类的的题不是很多。。。建议好好刷每一道题。。。。。

( 在给一个小小的OJ bug就是虽然说每两个case间输出空行。。其实不要理会。。。每个case都输出也会是对的。。。。OJ不会去判最后的那一行有没有空行。。。。不过只试用于现阶段呀。。。有一次校赛。。就专门卡这个。。还提示wa。。。可想而知当时的结果。。。。。)



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值