Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1585035
  • 博文数量: 399
  • 博客积分: 8508
  • 博客等级: 中将
  • 技术积分: 5302
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-14 09:28
个人简介

能力强的人善于解决问题,有智慧的人善于绕过问题。 区别很微妙,小心谨慎做后者。

文章分类

全部博文(399)

文章存档

2018年(3)

2017年(1)

2016年(1)

2015年(69)

2013年(14)

2012年(17)

2011年(12)

2010年(189)

2009年(93)

分类: LINUX

2009-12-02 14:30:26

最大流算法的一种实现就是不断寻找增广路径,一般推荐用BFS。最小费用最大流算法其实就是最大流算法的增强版限制路径搜索算法必须为最短路径算法,其中路径的权值即是费用。

算法本身不难,难在构图。通常需要构建超级汇点超级源点还有就是逆向路径的权值要设成正向路径权值的相反数,这点很关键

  1. #include   
  2. #include   
  3. using namespace std;  
  4. #define ABS(x) (x<0?-x:x)  
  5. #define MAXN 205  
  6. #define MIN(x,y) (x  
  7. #define INF  200005  
  8. int map[MAXN][MAXN],cost[MAXN][MAXN];  
  9. int pre[MAXN],max_flow[MAXN];
  10. //pre[] 记录结点的父节点 ; max_flow[] 记录从源点到当前点最多可以增加的容量,即限制值  
  11. int  flow[MAXN][MAXN];//记录当前网络中的流  
  12. int  dist[MAXN];//SPFA用
  13. queue<int> my_queue;  
  14. bool in_queue[MAXN];  
  15. bool SPFA(int num,int source,int sink)  
  16. {  
  17.     memset(in_queue,0,sizeof(in_queue));  
  18.     memset(pre,-1,sizeof(pre));  
  19.     for(int i=0;i
  20.     {  
  21.         dist[i]=INF;  
  22.     }  
  23.     dist[source]=0;  
  24.     my_queue.push(source);  
  25.     in_queue[source]=true;  
  26.       
  27.     max_flow[source]=INF;  
  28.     while(!my_queue.empty())  
  29.     {  
  30.         int temp=my_queue.front();  
  31.         my_queue.pop();  
  32.         for(int i=0;i
  33.         {  
  34.             if((map[temp][i]-flow[temp][i]>0)&&(dist[temp]+cost[temp][i]
  35.             {  
  36.                 dist[i]=dist[temp]+cost[temp][i];  
  37.                 if(!in_queue[i])  
  38.                 {  
  39.                     my_queue.push(i);  
  40.                     in_queue[i]=true;  
  41.                 }  
  42.                 pre[i]=temp;  
  43.                 max_flow[i]=MIN(max_flow[temp],(map[temp][i]-flow[temp][i]));//求得max_flow  
  44.             }  
  45.         }  
  46.         in_queue[temp]=false;  
  47.     }  
  48.     if(pre[sink]!=-1) return true;//sink的父节点不为初始值,说明已经找到了一条路径  
  49.     return false
  50. /*

        Bellman-Ford(G,w,s) boolean                             //G ,边集 函数 w s为源点

1        for each vertex v ∈ V(G) do            //初始化 1阶段

2            d[v] ←+∞

3        d[s] ←0;                          //1阶段结束

4        for i=1 to |v|-1 do              //2阶段开始,双重循环。

5        for each edge(u,v) ∈E(G) do//边集数组要用到,穷举每条边。

6              If d[v]> d[u]+ w(u,v) then  //松弛判断

7                 d[v]=d[u]+w(u,v)         //松弛操作   2阶段结束

8        for each edge(u,v) ∈E(G) do

9            If d[v]> d[u]+ w(u,v) then

10            Exit false

11    Exit true

*/

  1.     //一开始想用bellman-ford
  2.     //for(int i=0;i  
  3.     //{  
  4.     //  dist[i]=INF;  
  5.     //}  
  6.     //dist[source]=0;  
  7.     //memset(pre,-1,sizeof(pre));  
  8.     //max_flow[source]=INF; 
  9.     //  for(int j=0;j  
  10.     //  {  
  11.     //      for(int k=0;k  
  12.     //      {  
  13.     //          if((map[j][k]-flow[j][k]>0)&&(dist[j]+cost[j][k]  
  14.     //          {  
  15.     //              dist[k]=dist[j]+cost[j][k];  
  16.     //              pre[k]=j;  
  17.     //              max_flow[k]=MIN(max_flow[j],(map[j][k]-flow[j][k]));  
  18.     //          }  
  19.     //      }  
  20.     //  }
  21.     //if(pre[sink]!=-1) return true;  
  22.     //else return false;  
  23. }  
  24. int sum_cost,sum_flow;//最终结果  
  25. void min_cost_max_flow(int num,int source,int sink)
  26. //参数含义:结点数量  源点 汇点  
  27. {  
  28.     sum_cost=0,sum_flow=0;  
  29.     memset(flow,0,sizeof(flow));  
  30.     while(SPFA(num,source,sink))//一直循环,直到不存在增广最短路径  
  31.     {  
  32.         int k=sink;  
  33.         while(pre[k]>=0)  
  34.         {  
  35.             flow[pre[k]][k]+=max_flow[sink];   //将新的流量加入flow  
  36.             flow[k][pre[k]]=-flow[pre[k]][k];  //反向边,
  37.             k=pre[k];  
  38.         }  
  39.         sum_cost+=dist[sink];                 //最小费用
  40.         sum_flow+=max_flow[sink];             //费用最小时的最大流
  41.     }  
  42. }  
  43. int main()  
  44. {  
  45.     int N,M,ans;  
  46.     char temp[MAXN];  
  47.     int house[MAXN][2],house_index;  
  48.     int people[MAXN][2],people_index;  
  49.       
  50.     while(scanf("%d%d",&N,&M)&&N&&M)  
  51.     {  
  52.         memset(map ,0,sizeof(map));  
  53.         memset(cost,0,sizeof(cost));  
  54.         house_index=0;  
  55.         people_index=0;  
  56.         for(int i=0;i
  57.         {  
  58.             scanf("%s",temp);  
  59.             for(int j=0;j
  60.             {  
  61.                 if(temp[j]=='H')  
  62.                 {  
  63.                     house[house_index][0]=i;  
  64.                     house[house_index][1]=j;  
  65.                     house_index++;  
  66.                 }  
  67.                 else if(temp[j]=='m')  
  68.                 {  
  69.                     people[people_index][0]=i;  
  70.                     people[people_index][1]=j;  
  71.                     people_index++;  
  72.                 }  
  73.             }  
  74.         }  
  75.         for(int i=0;i
  76.         {  
  77.             for(int j=0;j
  78.             {  
  79.                 cost[i][people_index+j]=ABS((people[i][0]-house[j][0]))+ABS((people[i][1]-house[j][1]));  
  80.                 cost[people_index+j][i]=-cost[i][people_index+j];//逆向路径的权值要设成正向路径权值的相反数,这个很关键  
  81.                 map[i][people_index+j]=1;  
  82.             }  
  83.             map[people_index+house_index][i]=1;//构建超级汇点和超级源点  
  84.             map[people_index+i][people_index+house_index+1]=1;  
  85.         }  
  86.         min_cost_max_flow(people_index+house_index+2,people_index+house_index,people_index+house_index+1);  
  87.         printf("%d\n",sum_cost);  
  88.     }  
  89.     return 0;  

阅读(1542) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-08-23 21:14:02