网络流的建模 !!有上下界的网络流!![运输问题2]

来源:互联网 发布:电子表格软件下载 编辑:程序博客网 时间:2024/06/18 09:37

先来说连个比较简单的模型:

        多源多汇问题:

        对于这种问题,我们可以加一个超级源点和超级汇点,然后我们从超级源点到每一个源点都连一条上界为+00的边,同样也在每一个汇点到超级汇点都连一条上界为+00的边,这样跑一遍最大流即可。

        节点容量:

        我们可以把带容量的节点分裂成两个节点和一条边,边的容量和分裂前的点的容量相同。

下面我们这是开始说一下有上下界的情况

        ①无源汇有上下界的最大流。

        ②有源汇有上下界的最大流。

        ③有源汇有上下界的最小流。

①无源汇有上下界的最大流:

        建图模型:源点s,终点d。超级源点ss,超级终点dd。首先判断是否存在满足所有边上下界的可行流,方法可以转化成无源汇有上下界的可行流问题。怎么转换呢?

增设一条从d到s没有下界容量为无穷的边,那么原图就变成了一个无源汇的循环流图。接下来的事情一样,超级源点ss连i(du[i]>0),i连超级汇点(du[i]<0),

对(ss,dd)进行一次最大流,当maxflow等于所有(du[]>0)之和时,有可行流,否则没有。

当有可行流时,删除超级源点ss和超级终点dd,再对(s,d)进行一次最大流,此时得到的maxflow则为题目的解。为什么呢?因为第一次maxflow()只是求得所有满足下界的流量,而残留网络(s,d)路上还有许多自由流(没有和超级源点和超级汇点连接的边)没有流满,所有最终得到的maxflow=(第一次流满下界的流+第二次能流通的自由流)。

        ②有源汇有上下界的最大流:

        建图模型: 以前写的最大流默认的下界为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)求一次最大流即可,当所有附加边全部满流时(即maxflow==所有du[]>0之和),有可行解。

 额。。。③暂时还没学。。。


运输问题2

【问题描述】
    一个工厂每天生产若干商品,需运输到销售部门进行销售。从产地到销地要经过某些城镇,有不同的路线可以行走,每条两城镇间的公路都有一定的流量限制。为了保证公路的运营效率,每条公路都有一个容量下界,也就是至少应有多少车辆通过。每条公路还有一个容量上界,也就是最多应有多少车辆通过。请你计算,在不考虑其它车辆使用公路的前提下,如何充分利用所有的公路,使产地运输到销地的商品最多,最多能运输多少商品。
【输入格式】
输入文件有若干行
第一行,一个整数n,表示共有n个城市(2<=n<=100),产地是1号城市,销地是n号城市
下面有n行,每行有2*n个数字。第p行第2*q-1,2*q列的数字表示城镇p与城镇q之间有无公路连接。数字为0表示无,大于0表示有公路,且这两个数字分别表示该公路流量的下界,上界。
【输出格式】
输出文件有一行
第一行,1个整数n,表示最大流量为n。
【输入输出样例】
输入文件名: maxflowb.in
6
0 0 1 3 0 10 0 0 0 0 0 0 
0 0 0 0 0 0 5 7 0 0 0 0
0 0 0 0 0 0 0 0 2 8 0 0
0 0 0 0 1 3 0 0 0 0 3 5
0 0 2 4 0 0 0 0 0 0 2 6
0 0 0 0 0 0 0 0 0 0 0 0
输出文件名:maxflowb.out
10

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,du[120]={0},map[120][120]={0},pre[120],level[120]={0},gap[120]={0},map1[120][120][3]={0},num=0,ans=0;int ISAP(int x,int y){int u,v,i,minn,minm,maxn=0;memset(pre,-1,sizeof(pre));memset(level,0,sizeof(level));memset(gap,0,sizeof(gap));pre[x]=x;gap[0]=y;u=x;while(level[x]<y){for(v=1;v<=y;++v){if(map[u][v]>0&&level[v]+1==level[u]){    break;}}if(v<=y){pre[v]=u;u=v;if(v==y){minm=1000000000;for(i=v;i!=x;i=pre[i]){minm=min(minm,map[pre[i]][i]); }maxn+=minm;for(i=v;i!=x;i=pre[i]){map[pre[i]][i]-=minm;map[i][pre[i]]+=minm;}u=x;}}else{minn=y;for(v=1;v<=y;++v){if(map[u][v]>0){minn=min(minn,level[v]);}}minn+=1;gap[level[u]]-=1;if(!gap[level[u]]) break;level[u]=minn;gap[level[u]]+=1;u=pre[u];}}return maxn;}int main(){freopen("maxflowb.in","r",stdin);freopen("maxflowb.out","w",stdout);int i,j,x,y,m;scanf("%d",&n);for(i=1;i<=n;++i)  for(j=1;j<=n;++j){  scanf("%d%d",&x,&y);  map1[i][j][1]=x;  map1[i][j][2]=y;  }for(i=1;i<=n;++i){x=0;y=0;for(j=1;j<=n;++j){x+=map1[j][i][1];y+=map1[i][j][1];map[i][j]=map1[i][j][2]-map1[i][j][1];}du[i]=x-y;if(du[i]>0) map[n+1][i]=du[i],num+=du[i];else map[i][n+2]=-du[i];}map[n][1]=1000000000;ans=ISAP(n+1,n+2);    if(ans==num){    map[n][1]=0;    ans=ISAP(1,n);    printf("%d\n",ans);}else printf("0\n");}


0 0
原创粉丝点击