c语言求网络最大流,求网络的最小费用最大流,弧旁的数字是容量(运费)。

一.Ford和Fulkerson迭加算法.

基本思路:把各条弧上单位流量的费用看成某种长度,用求解最短路问题的方法确定一条自V1至Vn的最短路;在将这条最短路作为可扩充路,用求解最大流问题的方法将其上的流量增至最大可能值;而这条最短路上的流量增加后,其上各条弧的单位流量的费用要重新确定,如此多次迭代,最终得到最小费用最大流.

迭加算法:1) 给定目标流量F或∞,给定最小费用的初始可行流{fij}=0

2) 若V(f)=F,停止,f为最小费用流;否则转(3).

3) 构造{fij} 相应的新的费用有向图W(fij),在W(fij)寻找Vs到Vt的最小费用有向路P(最短路),沿P增加流f的流量直到F,转(2);若不存在从Vs到Vt的最小费用的有向路P,停止.f就是最小费用最大流.

具体解题步骤:

设图中双线所示路径为最短路径,费用有向图为W(fij).

在图(a)中给出零流 f,在图(b)中找到最小费用有向路,修改图(a)中的可行流,δ=min{4,3,5}=3,得图(c),再做出(c)的调整容量图,再构造相应的新的最小费用有向路得图(d), 修改图(c)中的可行流, δ=min{1,1,2,2}=1,得图(e),以此类推,一直得到图(h),在图(h)中以无最小费用有向路,停止,经计算:

图(h)中 最小费用=1*4+3*3+2*4+4*1+1*1+4*2+1*1+3*1=38

图(g)中 最大流=5

C语言程序如下(运行通过):

/*Ford和Fulkerson迭加算法*/

#include"stdio.h"

void main()

{int a,b,i,j,k,p,n,B[10][10],C[10][10],D[10][10],P[10][10][10];

printf("please input n:\n");

scanf("%d",&n);

printf("please input C[%d][%d],B[%d][%d]:\n",n,n,n,n);

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

scanf("%7d,%7d",&C[i][j],&B[i][j]); //输入各点(i,j)之间的容量C[i][j]和运费B[i][j]

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

{D[i][j]=B[i][j];

for(k=0;k<=n;k++)

P[i][j][k]=0;

if(D[i][j]<100) //注:100表示Vi到Vj之间无可行路

{P[i][j][i]=1;P[i][j][j]=1;}

}

for(k=0;k<=n;k++)

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

if(D[i][k]+D[k][j]

{D[i][j]=D[i][k]+D[k][j];

for(p=0;p<=n;p++)

P[i][j][p]=P[i][k][p]||P[k][j][p];

} //调用FLOYD算法

printf("D[%d][%d]:\n",n,n);

for(i=0;i<=n;i++)

{for(j=0;j<=n;j++)

printf("%7d",D[i][j]);

printf("\n");

} //由表D中的数值确定V0到V5的最短路

a=C[1][3];b=B[1][3]*D[0][5];

printf("a=%d,b=%d\n",a,b);

B[1][3]=100; //将容量已满的路改为不可行路

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

{D[i][j]=B[i][j];

for(k=0;k<=n;k++)

P[i][j][k]=0;

if(D[i][j]<100)

{P[i][j][i]=1;P[i][j][j]=1;}

}

for(k=0;k<=n;k++)

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

if(D[i][k]+D[k][j]

{D[i][j]=D[i][k]+D[k][j];

for(p=0;p<=n;p++)

P[i][j][p]=P[i][k][p]||P[k][j][p];

} //调用FLOYD算法

printf("D[%d][%d]:\n",n,n);

for(i=0;i<=n;i++)

{for(j=0;j<=n;j++)

printf("%7d",D[i][j]);

printf("\n");

} //由表D中的数值确定V0到V5的新最短路

a=a+C[1][2];b=b+D[0][5];

printf("a=%d,b=%d\n",a,b);

B[0][1]=100;B[1][2]=100;B[4][3]=100; //将容量已满的路改为不可行路

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

{D[i][j]=B[i][j];

for(k=0;k<=n;k++)

P[i][j][k]=0;

if(D[i][j]<100)

{P[i][j][i]=1;P[i][j][j]=1;}

}

for(k=0;k<=n;k++)

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

if(D[i][k]+D[k][j]

{D[i][j]=D[i][k]+D[k][j];

for(p=0;p<=n;p++)

P[i][j][p]=P[i][k][p]||P[k][j][p];

} //调用FLOYD算法

printf("D[%d][%d]:\n",n,n);

for(i=0;i<=n;i++)

{for(j=0;j<=n;j++)

printf("%7d",D[i][j]);

printf("\n");

} //由表D中的数值确定V0到V5的新最短路

a=a+C[2][4]-C[4][3];b=b+D[0][5];

printf("a=%d,b=%d\n",a,b);

B[2][4]=100; //将容量已满的路改为不可行路

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

{D[i][j]=B[i][j];

for(k=0;k<=n;k++)

P[i][j][k]=0;

if(D[i][j]<100)

{P[i][j][i]=1;P[i][j][j]=1;}

}

for(k=0;k<=n;k++)

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

if(D[i][k]+D[k][j]

{D[i][j]=D[i][k]+D[k][j];

for(p=0;p<=n;p++)

P[i][j][p]=P[i][k][p]||P[k][j][p];

} //调用FLOYD算法

printf("D[%d][%d]:\n",n,n);

for(i=0;i<=n;i++)

{for(j=0;j<=n;j++)

printf("%7d",D[i][j]);

printf("\n");

} //检验有无V0到V5的新最短路

}

运行结果:

please input n:

5

please input C[5][5],B[5][5]:

0,0 4,1 5,3 0,100 0,100 0,100

0,100 0,0 1,1 3,3 0,100 0,100

0,100 0,100 0,0 0,100 2,4 0,100

0,100 0,100 0,100 0,0 0,100 5,2

0,100 0,100 0,100 1,1 0,0 2,4

0,100 0,100 0,100 0,100 0,100 0,0

D[5][5]:

0 1 2 4 6 6

100 0 1 3 5 5

100 100 0 5 4 7

100 100 100 0 100 2

100 100 100 1 0 3

100 100 100 100 100 0

a=3,b=18

D[5][5]:

0 1 2 7 6 9

100 0 1 6 5 8

100 100 0 5 4 7

100 100 100 0 100 2

100 100 100 1 0 3

100 100 100 100 100 0

a=4,b=27

D[5][5]:

0 100 3 100 7 11

100 0 100 100 100 100

100 100 0 100 4 8

100 100 100 0 100 2

100 100 100 100 0 4

100 100 100 100 100 0

a=5,b=38

D[5][5]:

0 100 3 100 100 100

100 0 100 100 100 100

100 100 0 100 100 100

100 100 100 0 100 2

100 100 100 100 0 4

100 100 100 100 100 0

//注:100表示Vi到Vj之间无可行路

二.圈算法:

1) 利用Ford和Fulkson标号算法找出流量为F(<=最大流)的流f.

2) 构造f对应的调整容量的流网络N'(f).

3) 搜索N'(f)中的负费用有向图C(Floyd算法),若没有则停止,否则转(4).

4) 在C上找出最大的循环流,并加到N上去,同时修改N'(F)中C的容量,转(3).

具体解题步骤:

利用Ford和Fulkson标号算法,得网络的最大流F=5,见图(a),由图(a)构造相应的调整容量的流网络(b),图(b)中不存在负费用有向图,故停止.经计算:

图(b)中 最小费用= 4*1+3*1+1*1+3*3+4*2+1*1+4*1+2*4=38

图(a)中 最大流为F=5

C语言程序如下(运行通过):

/*圈算法*/

#include"stdio.h"

int min(int x,int y)

{if(x

else return(y);

}

void main()

{int a=0,b=0,i,j,k,p,n,t,A[10][10],P[10][10],B[10][10],C[10][10],D[10][10];

printf("please input n:\n");

scanf("%d",&n);

printf("please input C[%d][%d],B[%d][%d]:\n",n,n,n,n);

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

scanf("%7d,%7d",&C[i][j],&B[i][j]); //输入各点(i,j)之间的容量C[i][j]和运费B[i][j]

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

{A[i][j]=C[i][j];D[i][j]=0;P[i][j]=B[i][j];}

for(i=n;i>1;i--)

for(j=i-1;j>0;j--)

for(k=j-1;k>=0;k--)

if(A[j][i]!=0&&A[k][j]!=0)

D[k][j]=min(A[j][i],A[k][j]);

printf("D[%d][%d]:\n",n,n);

for(i=0;i<=n;i++)

{for(j=0;j<=n;j++)

printf("%7d",D[i][j]);

printf("\n");

}

for(i=0;i

for(j=i+1;j

for(k=j+1;k<=n;k++)

if(D[i][j]!=0&&D[j][k]!=0)

if(D[i][j]+D[j][k]==C[i][j])

{A[i][j]=0;A[j][k]=0;A[j-i][k-j]=0;

P[i][j]=100;P[j][k]=100;P[j-i][k-j]=0;

a=a+C[i][j];

b=b+B[i][j]*C[i][j]+B[j][k]*C[j][k]+B[j-i][k-j]*C[j-i][k-j];

for(p=k+1;p<=n;p++)

if(C[i][j]

{b=b+B[k][p]*C[i][j];

A[k][p]=C[k][p]-C[i][j];

}

for(p=k-j+1;p<=n;p++)

if(C[j-i][k-j]

{b=b+B[k-j][p]*C[j-i][k-j]+B[4][3]*C[4][3];

A[k-j][p]=C[k-j][p]-C[j-i][k-j];

}

A[4][3]=0;

}

printf("a=%d,b=%d\n",a,b);

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

D[i][j]=0;

for(i=n;i>1;i--)

for(j=i-1;j>0;j--)

for(k=j-1;k>=0;k--)

if(A[j][i]!=0&&A[k][j]!=0)

D[k][j]=min(A[j][i],A[k][j]);

printf("D[%d][%d]:\n",n,n);

for(i=0;i<=n;i++)

{for(j=0;j<=n;j++)

printf("%7d",D[i][j]);

printf("\n");

}

for(i=0;i

for(j=i+1;j

for(k=j+1;k<=n;k++)

if(D[i][j]!=0&&D[j][k]!=0)

if(D[i][j]==D[j][k])

for(p=k+1;p<=n;p++)

{t=min(min(A[i][j],A[j][k]),min(A[j][k],A[k][p]));

a=a+t;

b=b+t*(B[i][j]+B[j][k]+B[k][p]);

}

printf("a=%d,b=%d\n",a,b);

}

运行结果:

please input n:

5

please input C[5][5],B[5][5]:

0,0 4,1 5,3 0,100 0,100 0,100

0,100 0,0 1,1 3,3 0,100 0,100

0,100 0,100 0,0 0,100 2,4 0,100

0,100 0,100 0,100 0,0 0,100 5,2

0,100 0,100 0,100 1,1 0,0 2,4

0,100 0,100 0,100 0,100 0,100 0,0

D[5][5]:

0 1 2 0 0 0

0 0 1 3 0 0

0 0 0 0 2 0

0 0 0 0 0 0

0 0 0 0 0 0

0 0 0 0 0 0

a=4,b=27

D[5][5]:

0 0 1 0 0 0

0 0 0 0 0 0

0 0 0 0 1 0

0 0 0 0 0 0

0 0 0 0 0 0

0 0 0 0 0 0

a=5,b=38

//注:100表示Vi到Vj之间无可行路

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值