先来说连个比较简单的模型:
多源多汇问题:
对于这种问题,我们可以加一个超级源点和超级汇点,然后我们从超级源点到每一个源点都连一条上界为+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。
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
#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");
}