数模论坛

 找回密码
 注-册-帐-号
搜索
热搜: 活动 交友 discuz
查看: 4777|回复: 2

[原创]关于最小费用最大流的一个C算法

[复制链接]
发表于 2005-7-17 22:40:00 | 显示全部楼层 |阅读模式
<>//2005.4.12 <BR>//written by shenhui<BR>//此算法必须指定要求的最大流stream,如果结果无限循环的出现<BR>//一些字或者什么也不出现,则说明该图达不到此流量。<BR>#include "iostream.h"                       <BR>#define max 10000<BR>#define n  5                //根据不同问题可修改大小<BR>#define stream  10          //根据不同问题可修改<BR> <BR> <BR>//最大容量矩阵<BR>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}};<BR>//实际流量矩阵<BR>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}};<BR>//费用矩阵<BR>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,max,0}};<BR>//增广链向量<BR>int p[n]={0,0,0,0,0};         //原点到各点的最短路径<BR>int D[n];                     //原点到各点的路长(用于Dijkstra法中)<BR>int pt[n]={0,0,0,0,0};       //原点到各点的路长(用于逐次逼近法中)</P>
<>int maxflow;               //设置最大流量</P>

<><BR>//----------------------------计算Vs--Vt最短路径模块---------------------------------------------//</P>
<P>void Dijkstra()                  //求源点V0到其余顶点的最短路径及其长度;得到一条增广链<BR>{<BR> int s[n];               //D[n]最后保存各点的最短路径长度<BR> int i,j,k,vl,pre;             <BR> int min;<BR> int inf=20000;<BR> vl=0;                    //求V0到Vn的增广链<BR> for(i=0;i&lt;n;i++)<BR> { <BR>  D=money[vl];            //置初始距离值      <BR>  if((D!=max) &amp;&amp; (D!=0)) p=1;<BR>  else p=0;<BR> }</P>
<P> for(i=0;i&lt;n;i++)  s=0;            <BR> s[vl]=1; D[vl]=0;<BR> for(i=0;i&lt;n;i++)<BR> {<BR>  min=inf;<BR>  for(j=0;j&lt;n;j++)<BR>   if((!s[j]) &amp;&amp; (D[j]&lt;min))<BR>   {<BR>    min=D[j];<BR>    k=j;<BR>   }<BR>  s[k]=1;<BR>  if(min==max)  break;<BR>  for(j=0;j&lt;n;j++)<BR>     if((!s[j])  &amp;&amp;  (D[j]&gt;D[k]+money[k][j]))<BR>     {<BR>      D[j]=D[k]+money[k][j];<BR>      p[j]=k+1;<BR>     }<BR> }         //此时所有顶点都已扩充到红点集S中<BR> <BR> <BR> cout&lt;&lt;"Vs到Vt的最短路径为(长和径):\n";<BR> for(i=0;i&lt;n;i++)<BR> {<BR>  if(i=n-1){<BR>  cout&lt;&lt;D&lt;&lt;"   "&lt;&lt;i+1;    //这里不需要打印<BR>  pre=p;<BR>  while (pre!=0)<BR>  {<BR>   cout&lt;&lt;"&lt;-- "&lt;&lt;pre;     //这里不需要打印<BR>   pre=p[pre-1];           //p[]中保存的路径的顶点标号从1开始,不是0;<BR>  }<BR>  cout&lt;&lt;"\n";}<BR> }<BR>}                                    <BR>//-----------------------------------END Dijkstra()-----------------------------------------//</P>

<P><BR>//------------------用最大流算法的方法调整实际流量矩阵flow[][],以扩充其流量----------------//<BR>void modify()    <BR>{<BR> int i,min;<BR> int pre;<BR>    if(D[n-1]==max) <BR> {<BR>  cout&lt;&lt;"不存在增广链";<BR>        return;<BR> }</P>
<P> pre=p[n-1];<BR> i=n-1;<BR> min=c[pre-1]-flow[pre-1];           //增广路上的最后一条边的长<BR> while(pre!=0)                            //再增广路上算出所能增加流量的最大值<BR> {<BR>     i=pre-1;<BR>  pre=p[pre-1];<BR>  if(min&gt;c[pre-1]-flow[pre-1])<BR>   min=c[pre-1]-flow[pre-1];<BR>  if(pre==1)<BR>   pre=0;<BR> }<BR>    if((min+maxflow)&gt;stream)<BR>  min=stream-maxflow;<BR> pre=p[n-1];                    //在增广链上添加流量<BR> i=n-1;<BR> flow[pre-1]+=min;<BR> while(pre!=0)<BR> {<BR>  i=pre-1;<BR>  pre=p[pre-1];<BR>  flow[pre-1]+=min;<BR>  if(pre==1)<BR>   pre=0;<BR> }<BR>}<BR>//----------------------------------END modify()----------------------------------//</P>

<P><BR>//--------------------------------调整费用矩阵money[][]-----------------------------//<BR>void modifymoney()                        <BR>{<BR> int i,j;<BR> int moneypre[n][n];<BR>    for(i=0;i&lt;n;i++)<BR>  for(j=0;j&lt;n;j++)<BR>  moneypre[j]=money[j];<BR> for(i=0;i&lt;n;i++)<BR>  for(j=0;j&lt;n;j++)<BR>  {<BR>   if(i&lt;j){<BR>   if(c[j]!=max &amp;&amp; c[j]&gt;flow[j])<BR>    money[j]=moneypre[j];<BR>   if((c[j]!=max &amp;&amp; c[j]==flow[j]) || (c[j]==max &amp;&amp; flow[j]==max))<BR>    money[j]=max;}<BR>   if(i&gt;j){<BR>   if(  flow[j]&gt;0 )<BR>    money[j]=-moneypre[j];<BR>   if(flow[j]==0)<BR>    money[j]=max;}<BR>  }<BR>     for(i=0;i&lt;n;i++)<BR>  for(j=0;j&lt;n;j++)<BR>  {<BR>   if(i==j)<BR>    money[j]=0;<BR>            if(money[j]==-max)<BR>    money[j]=max;<BR>  }<BR>}<BR>//----------------------------------END modifymoney()----------------------------------//</P>

<P>//----------------------------采用逐次逼近法得到一条增广链----------------------------//<BR>void approach()                                <BR>{<BR> int pf[n],ptf[n]={0,0,0,0,0};      //当N变动时,0的个数应与N一致<BR> int min=max;<BR> int i,j,flag;<BR> for(j=0;j&lt;n;j++)<BR>  pt[j]=money[0][j];             //直接距离做初始解<BR>    do{<BR>  flag=1;<BR>  for(j=0;j&lt;n;j++)                         <BR>     pf[j]=pt[j];      //将上一次得到的路径迭代结果保存入pf[]<BR>  for(i=0;i&lt;n;i++)<BR>  {<BR>   min=pt;<BR>   for(j=0;j&lt;n;j++)<BR>   {<BR>     <BR>      if(min&gt;(pt[j]+money[j]))<BR>       min=pt[j]+money[j];<BR>   }<BR>            ptf=min;<BR>  }<BR>   <BR>  for(i=0;i&lt;n;i++)<BR>  { <BR>    pt=ptf;<BR>     if(pf!=pt)<BR>    flag=0;     //两次迭代的值不同,继续<BR>  }<BR> }while(flag==0);</P>
<P> j=n-1;  <BR>    for(i=0;i&lt;j;i++)              //找出最短路径走向<BR> if(pt+money[j]==pt[j])<BR>  {<BR>     p[j]=i+1;   //p[j]中的下标从1开始<BR>        if(p[j]==1) break; <BR>     j=i;<BR>     i=-1;<BR>   <BR>     <BR>  }        <BR>    for(i=0;i&lt;n;i++)      <BR>  D=pt;<BR>}<BR>//------------------------------END approach()------------------------------//</P>

<P><BR>void main()<BR>{<BR> int i,j;<BR> Dijkstra();<BR> <BR>  while( 1 )    <BR>  {     <BR>    modify();   //调整流量矩阵<BR>    maxflow=0;<BR>    for(j=0;j&lt;n;j++)<BR>    {<BR>     if(flow[0][j]!=max)<BR>   maxflow+=flow[0][j];<BR>    }<BR>    if(maxflow==stream)  break;  <BR>    modifymoney();<BR>    approach();         //采用逐次逼近法得到一条增广链    <BR>    <BR>           <BR>  <BR>  }<BR>    <BR> <BR> cout&lt;&lt;"流量矩阵:\n";<BR>    for(i=0;i&lt;n;i++)                    //<BR> {<BR>  for(j=0;j&lt;n;j++)<BR>   cout&lt;&lt;flow[j]&lt;&lt;"  ";<BR>        cout&lt;&lt;"\n";<BR> }<BR> <BR>   cout&lt;&lt;"费用矩阵:\n";<BR> for(i=0;i&lt;n;i++)                    //<BR> {<BR>  for(j=0;j&lt;n;j++)<BR>   cout&lt;&lt;money[j]&lt;&lt;"  ";<BR>        cout&lt;&lt;"\n";<BR> }<BR>}</P>
发表于 2005-7-20 03:15:36 | 显示全部楼层
不错,不错。辛苦了[em17]
发表于 2005-8-26 03:58:11 | 显示全部楼层
<>楼主  辛苦拉</P>
您需要登录后才可以回帖 登录 | 注-册-帐-号

本版积分规则

小黑屋|手机版|Archiver|数学建模网 ( 湘ICP备11011602号 )

GMT+8, 2024-11-27 10:33 , Processed in 0.055406 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表