最小费用最大流学习笔记

     简单的说就是最大流之EK算法的改进。

     最小费用最大流我是这么理解的:当达到最大流量时,要保证此时最大流量的费用是最小的,为什么这么说呢,因为最大流可能有多种,路径不同费用不同。

    现在需要改进的就是在求得最大流的同时如何保证费用最小,我们可以对费用进行操作。首先要找到一个超级源点s和一个超级终点t,以单位流量费用为(u,v)边的权值,然后进行spfa单源最短路操作,一次操作下来从起点s到终点t必是本次的费用了,然后找到这条本次最小费用路径的边的最小容量(设为sum),那么这条路径的边的容量都要减去sum值了,反向边要增加sum容量值(联系最大流之EK算法想想为什么)。 重复进行此操作,当spfa得到的源点s和终点t的距离为INF时,也就是不存在这样的最小费用边了,此时得到的即为最小费用最大流了。

   需要注意几点:

  1、注意超级源点和超级终点的建立。

  2、初始化时,正向边的单位流量费用为cost[u][v],那么反向边的单位流量费用就为-cost[u][v]。因为回流费用减少,我是联系水流流动考虑的。

 3、费用cost数组和容量cap数组每次都要初始化为0,切记。

 

附上我的模板:

View Code
 1 #include <iostream>

 2 #include <cmath>

 3 #include <cstdio>

 4 #include <cstring>

 5 #include <algorithm>

 6 using namespace std;

 7 

 8 const int maxn=210;

 9 const int oo=0x3fffffff;

10 char map[maxn][maxn];

11 int dis[2*maxn],que[2*maxn],inque[2*maxn],pre[2*maxn];

12 int cost[2*maxn][2*maxn];

13 int cap[2*maxn][2*maxn];

14 int n, m, s, t, a, b, max_flow;  ///s为超级源点,t为超级终点

15 

16 int spfa()

17 {

18     int h=0, l=0;

19     for(int i=0; i<=t; i++)

20         dis[i]=oo, inque[i]=0, pre[i]=-1;

21     dis[s]=0;

22     que[l++]=s;

23     inque[s]=1;

24     while(l!=h)

25     {

26         int u=que[h++];

27         inque[u]=0;

28         if(h==maxn) h=0;

29         for(int i=0; i<=t; i++)

30         {

31             if(cap[u][i]&&dis[i]>dis[u]+cost[u][i])

32             {

33                 dis[i]=dis[u]+cost[u][i];

34                 pre[i]=u;

35                 if(!inque[i])

36                 {

37                     inque[i]=1;

38                     que[l++]=i;

39                     if(l==maxn) l=0;

40                 }

41             }

42         }

43     }

44     return pre[t];

45 }

46 

47 void flowmax()

48 {

49     int sum=oo;

50     while(spfa()!=-1)

51     {

52         for(int i=t; i!=0; i=pre[i])

53             sum=min(sum,cap[pre[i]][i]);

54         for(int i=t; i!=0; i=pre[i])

55         {

56             int u=pre[i], v=i;

57             cap[u][v]-=sum;

58             cap[v][u]+=sum;

59             max_flow+=sum*cost[u][v];

60         }

61     }

62 }

63 

64 int main()

65 {

66     while(cin >> n >> m, n+m)

67     {

68         s=0;

69         t=a+b+1;

70         max_flow=0;

71         memset(cost,0,sizeof(cost)); ///初始化

72         memset(cap,0,sizeof(cap));  ///初始化

73         for(int i=1; i<=a; i++)

74             cap[s][i]=1;

75         for(int i=1; i<=b; i++)

76             cap[i+a][t]=1;

77         for(int i=1; i<=a; i++)

78             for(int j=1; j<=b; j++)

79             {

80                 int c=fabs(P[i].x-H[j].x)+fabs(P[i].y-H[j].y);

81                 cost[i][j+a]=c;

82                 cost[j+a][i]=-c;  ///!!!可能回流

83                 cap[i][j+a]=1;

84             }

85         flowmax();

86         cout <<max_flow <<endl;

87     }

88     return 0;

89 }

 

 

 

你可能感兴趣的:(学习笔记)