✅ 操作成功!

最小费用最大流

发布时间:2023-06-12 作者:admin 来源:文学

最小费用最大流

最小费用最大流

动物是怎么睡觉的-家常炖鱼

2023年3月17日发(作者:纳尼亚传奇读后感)

//此算法必须指定要求的最大流stream,如果结果无限循环的出现

//一些字或者什么也不出现,则说明该图达不到此流量。

#include"iostream.h"

#definemax10000

#definen5//根据不同问题可修改大小

#definestream10//根据不同问题可修改

//最大容量矩阵

int

c[n][n]={{0,10,8,max,max},{max,0,max,2,7},{max,5,0,10,max},{max,max,max,0,4},{max,max,max,max,0

}};

//实际流量矩阵

int

flow[n][n]={{0,0,0,max,max},{max,0,max,0,0},{max,0,0,0,max},{max,max,max,0,0},{max,max,max,max,

0}};

//费用矩阵

int

money[n][n]={{0,4,1,max,max},{max,0,max,6,1},{max,2,0,3,max},{max,max,max,0,2},{max,max,max,ma

x,0}};

//增广链向量

intp[n]={0,0,0,0,0};//原点到各点的最短路径

intD[n];//原点到各点的路长(用于Dijkstra法中)

intpt[n]={0,0,0,0,0};//原点到各点的路长(用于逐次逼近法中)

intmaxflow;//设置最大流量

//----------------------------计算Vs--Vt最短路径模块---------------------------------------------//

voidDijkstra()//求源点V0到其余顶点的最短路径及其长度;得到一条增广链

{

ints[n];//D[n]最后保存各点的最短路径长度

inti,j,k,vl,pre;

intmin;

intinf=20000;

vl=0;//求V0到Vn的增广链

for(i=0;i

{

D[i]=money[vl][i];//置初始距离值

if((D[i]!=max)&&(D[i]!=0))p[i]=1;

elsep[i]=0;

}

for(i=0;i

s[vl]=1;D[vl]=0;

for(i=0;i

{

min=inf;

for(j=0;j

if((!s[j])&&(D[j]

{

min=D[j];

k=j;

}

s[k]=1;

if(min==max)break;

for(j=0;j

if((!s[j])&&(D[j]>D[k]+money[k][j]))

{

D[j]=D[k]+money[k][j];

p[j]=k+1;

}

}//此时所有顶点都已扩充到红点集S中

cout<<"Vs到Vt的最短路径为(长和径):n";

for(i=0;i

{

if(i=n-1){

cout<

pre=p[i];

while(pre!=0)

{

cout<<"<--"<

pre=p[pre-1];//p[]中保存的路径的顶点标号从1开始,不是0;

}

cout<<"n";}

}

}

//-----------------------------------ENDDijkstra()-----------------------------------------//

//------------------用最大流算法的方法调整实际流量矩阵flow[][],以扩充其流量----------------//

voidmodify()

{

inti,min;

intpre;

if(D[n-1]==max)

{

cout<<"不存在增广链";

return;

}

pre=p[n-1];

i=n-1;

min=c[pre-1][i]-flow[pre-1][i];//增广路上的最后一条边的长

while(pre!=0)//再增广路上算出所能增加流量的最大值

{

i=pre-1;

pre=p[pre-1];

if(min>c[pre-1][i]-flow[pre-1][i])

min=c[pre-1][i]-flow[pre-1][i];

if(pre==1)

pre=0;

}

if((min+maxflow)>stream)

min=stream-maxflow;

pre=p[n-1];//在增广链上添加流量

i=n-1;

flow[pre-1][i]+=min;

while(pre!=0)

{

i=pre-1;

pre=p[pre-1];

flow[pre-1][i]+=min;

if(pre==1)

pre=0;

}

}

//----------------------------------ENDmodify()----------------------------------//

//--------------------------------调整费用矩阵money[][]-----------------------------//

voidmodifymoney()

{

inti,j;

intmoneypre[n][n];

for(i=0;i

for(j=0;j

moneypre[i][j]=money[i][j];

for(i=0;i

for(j=0;j

{

if(i

if(c[i][j]!=max&&c[i][j]>flow[i][j])

money[i][j]=moneypre[i][j];

if((c[i][j]!=max&&c[i][j]==flow[i][j])||(c[i][j]==max&&flow[i][j]==max))

money[i][j]=max;}

if(i>j){

if(flow[j][i]>0)

money[i][j]=-moneypre[j][i];

if(flow[j][i]==0)

money[i][j]=max;}

}

for(i=0;i

for(j=0;j

{

if(i==j)

money[i][j]=0;

if(money[i][j]==-max)

money[i][j]=max;

}

}

//----------------------------------ENDmodifymoney()----------------------------------//

//----------------------------采用逐次逼近法得到一条增广链----------------------------//

voidapproach()

{

intpf[n],ptf[n]={0,0,0,0,0};//当N变动时,0的个数应与N一致

intmin=max;

inti,j,flag;

for(j=0;j

pt[j]=money[0][j];//直接距离做初始解

do{

flag=1;

for(j=0;j

pf[j]=pt[j];//将上一次得到的路径迭代结果保存入pf[]

for(i=0;i

{

min=pt[i];

for(j=0;j

{

if(min>(pt[j]+money[j][i]))

min=pt[j]+money[j][i];

}

ptf[i]=min;

}

for(i=0;i

{

pt[i]=ptf[i];

if(pf[i]!=pt[i])

flag=0;//两次迭代的值不同,继续

}

}while(flag==0);

j=n-1;

for(i=0;i

if(pt[i]+money[i][j]==pt[j])

{

p[j]=i+1;//p[j]中的下标从1开始

if(p[j]==1)break;

j=i;

i=-1;

}

for(i=0;i

D[i]=pt[i];

}

//------------------------------ENDapproach()------------------------------//

voidmain()

{

inti,j;

Dijkstra();

while(1)

{

modify();//调整流量矩阵

maxflow=0;

for(j=0;j

{

if(flow[0][j]!=max)

maxflow+=flow[0][j];

}

if(maxflow==stream)break;

modifymoney();

approach();//采用逐次逼近法得到一条增广链

}

cout<<"流量矩阵:n";

for(i=0;i

{

for(j=0;j

cout<

cout<<"n";

}

cout<<"费用矩阵:n";

for(i=0;i

{

for(j=0;j

cout<

cout<<"n";

}

}

👁️ 阅读量:0