网络流的费用: 在实际应用中,与网络流有关的问题,不仅涉及流量,而且还有费用的因素。网络的每一条边(v,w)除了给定容量cap(v,w)外,还定义了一个单位流量费用cost(v,w)。对于网络中一个给定的流flow,其费用定义为:
最小费用最大流问题 给定网络G,要求G的一个最大用流flow,使流的总费用最小。
求解MCMF问题的算法: 在这里各种算法的证明以及原理的详解不再赘述,仅仅介绍算法的过程。相关内容感兴趣的同学可以自己去搜索资料。 最小费用最大流最常用和基本的算法我们可以称它为最小费用路算法,其思想与求最大流的增广路算法类似,不断在残流网络中寻找从源s到汇t的最小费用路,即残流网络中从s到t的以费用为权的最短路,然后沿最小费用路增流,直至找到最小费用流。 残流网络中边的费用定义为:
当残流网络中边(v,w)是向前边时,其费用为cost(v,w); 当(v,w)是向后边时,其费用为-cost(w,v)。
最小费用流的最小费用路算法
步骤0:初始可行0流。 步骤1:如果不存在最小费用路,则计算结束,已经找到最小费用流;否则用最短路算法在残流网络中找从s到t的最小费用可增广路,转步骤2。 步骤2:沿找到的最小费用可增广路增流,并转步骤1。
最小费用路算法的复杂度主要依靠于求最短路的方法,由于负权的存在,不会选择dijstra等算法,一般bellman-ford,spfa等用来解决费用流的最短路问题。
模版题:
POJ 2135
代码:
View Code
1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 #include <queue>
5 using namespace std;
6 int sumFlow;
7 const int MAXN = 1010;
8 const int MAXM = 1000200;
9 const int INF = 1000000000;
10 struct Edge
11 {
12 int u;
13 int v;
14 int cap;
15 int cost;
16 int next;
17 }edge[MAXM<<2];
18 int NE;
19 int head[MAXN], dist[MAXN], pp[MAXN];
20 bool vis[MAXN];
21 void init()
22 {
23 NE=0;
24 memset(head,-1,sizeof(head));
25 }
26 void addedge(int u,int v,int cap,int cost)
27 {
28 edge[NE].u=u;edge[NE].v=v;edge[NE].cap=cap;edge[NE].cost=cost;
29 edge[NE].next=head[u];head[u]=NE++;
30 edge[NE].u=v;edge[NE].v=u;edge[NE].cap=0;edge[NE].cost=-cost;
31 edge[NE].next=head[v];head[v]=NE++;
32 }
33 bool SPFA(int s,int t,int n)
34 {
35 int i,u,v;
36 queue<int>qu;
37 memset(vis,false,sizeof(vis));
38 memset(pp,-1,sizeof(pp));
39 for(i=0;i<=n;i++)
40 dist[i]=INF;
41 vis[s]=true;
42 dist[s]=0;
43 qu.push(s);
44 while(!qu.empty())
45 {
46 u=qu.front();
47 qu.pop();
48 vis[u]=false;
49 for(i=head[u];i!=-1;i=edge[i].next)
50 {
51 v=edge[i].v;
52 if(edge[i].cap&&dist[v]>dist[u]+edge[i].cost)
53 {
54 dist[v]=dist[u]+edge[i].cost;
55 pp[v]=i;
56 if(!vis[v])
57 {
58 qu.push(v);
59 vis[v]=true;
60 }
61 }
62 }
63 }
64 if(dist[t]==INF)
65 return false;
66 return true;
67 }
68 int MCMF(int s,int t,int n)
69 {
70 int flow=0; // 总流量
71 int i,minflow,mincost;
72 mincost=0;
73 while(SPFA(s,t,n))
74 {
75 minflow=INF+1;
76 for(i=pp[t];i!=-1;i=pp[edge[i].u])
77 if(edge[i].cap<minflow)
78 minflow=edge[i].cap;
79 flow+=minflow;
80 for(i=pp[t];i!=-1;i=pp[edge[i].u])
81 {
82 edge[i].cap-=minflow;
83 edge[i^1].cap+=minflow;
84 }
85 mincost+=dist[t]*minflow;
86 }
87 sumFlow=flow; // 最大流
88 return mincost;
89 }
90 int main()
91 {
92 int n,m;
93 int u,v,c;
94 while(~scanf("%d%d",&n,&m))
95 {
96 init();
97 int S=0;
98 int T=n+1;
99 while(m--)
100 {
101 scanf("%d%d%d",&u,&v,&c);
102 addedge(u,v,1,c);
103 addedge(v,u,1,c);
104 }
105 addedge(S,1,2,0);
106 addedge(n,T,2,0);
107 int ans=MCMF(S,T,T+1);
108 printf("%d\n",ans);
109 }
110 return 0;
111 }
112
2 #include <cstring>
3 #include <cstdio>
4 #include <queue>
5 using namespace std;
6 int sumFlow;
7 const int MAXN = 1010;
8 const int MAXM = 1000200;
9 const int INF = 1000000000;
10 struct Edge
11 {
12 int u;
13 int v;
14 int cap;
15 int cost;
16 int next;
17 }edge[MAXM<<2];
18 int NE;
19 int head[MAXN], dist[MAXN], pp[MAXN];
20 bool vis[MAXN];
21 void init()
22 {
23 NE=0;
24 memset(head,-1,sizeof(head));
25 }
26 void addedge(int u,int v,int cap,int cost)
27 {
28 edge[NE].u=u;edge[NE].v=v;edge[NE].cap=cap;edge[NE].cost=cost;
29 edge[NE].next=head[u];head[u]=NE++;
30 edge[NE].u=v;edge[NE].v=u;edge[NE].cap=0;edge[NE].cost=-cost;
31 edge[NE].next=head[v];head[v]=NE++;
32 }
33 bool SPFA(int s,int t,int n)
34 {
35 int i,u,v;
36 queue<int>qu;
37 memset(vis,false,sizeof(vis));
38 memset(pp,-1,sizeof(pp));
39 for(i=0;i<=n;i++)
40 dist[i]=INF;
41 vis[s]=true;
42 dist[s]=0;
43 qu.push(s);
44 while(!qu.empty())
45 {
46 u=qu.front();
47 qu.pop();
48 vis[u]=false;
49 for(i=head[u];i!=-1;i=edge[i].next)
50 {
51 v=edge[i].v;
52 if(edge[i].cap&&dist[v]>dist[u]+edge[i].cost)
53 {
54 dist[v]=dist[u]+edge[i].cost;
55 pp[v]=i;
56 if(!vis[v])
57 {
58 qu.push(v);
59 vis[v]=true;
60 }
61 }
62 }
63 }
64 if(dist[t]==INF)
65 return false;
66 return true;
67 }
68 int MCMF(int s,int t,int n)
69 {
70 int flow=0; // 总流量
71 int i,minflow,mincost;
72 mincost=0;
73 while(SPFA(s,t,n))
74 {
75 minflow=INF+1;
76 for(i=pp[t];i!=-1;i=pp[edge[i].u])
77 if(edge[i].cap<minflow)
78 minflow=edge[i].cap;
79 flow+=minflow;
80 for(i=pp[t];i!=-1;i=pp[edge[i].u])
81 {
82 edge[i].cap-=minflow;
83 edge[i^1].cap+=minflow;
84 }
85 mincost+=dist[t]*minflow;
86 }
87 sumFlow=flow; // 最大流
88 return mincost;
89 }
90 int main()
91 {
92 int n,m;
93 int u,v,c;
94 while(~scanf("%d%d",&n,&m))
95 {
96 init();
97 int S=0;
98 int T=n+1;
99 while(m--)
100 {
101 scanf("%d%d%d",&u,&v,&c);
102 addedge(u,v,1,c);
103 addedge(v,u,1,c);
104 }
105 addedge(S,1,2,0);
106 addedge(n,T,2,0);
107 int ans=MCMF(S,T,T+1);
108 printf("%d\n",ans);
109 }
110 return 0;
111 }
112