标签:des style blog http color os io strong
网络流的费用: 在实际应用中,与网络流有关的问题,不仅涉及流量,而且还有费用的因素。网络的每一条边(v,w)除了给定容量cap(v,w)外,还定义了一个单位流量费用cost(v,w)
最小费用最大流问题 给定网络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等用来解决费用流的最短路问题。
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11372 | Accepted: 4218 |
Description
Input
Output
Sample Input
4 5 1 2 1 2 3 1 3 4 1 1 3 2 2 4 2
Sample Output
6
这道题有两个值得注意的地方,第一个是建图,无向边只允许通过一次,往返的两条线路可以看成是从源点到汇点的两条线路,所以只要从附加源点向源点连一条容量为2的边和从汇点向附加汇点连一条容量为2的边就可以限线路为两条.
第一个值得注意的地方是由于有重边的出现,所以这道题要用邻接表实现.
邻接表相对于邻接阵来说,空间需求和时间需求都有优势,但是比较麻烦.
摘自http://blog.sina.com.cn/s/blog_93ced90c010184r4.html
<pre name="code" class="cpp">#include"stdio.h" #include"string.h" #include"queue" using namespace std; #define M 1100 const int inf=0x7fffffff; struct node { int u,v,c,f,next; //C为花费,F为flow流量 }e[M*40]; int pre[M],dis[M],head[M],t; int vis[M]; void add1(int u,int v,int c,int f) { e[t].u=u; e[t].v=v; e[t].c=c; e[t].f=f; e[t].next=head[u]; head[u]=t++; } void add(int u,int v,int c,int f) { add1(u,v,c,f); add1(v,u,-c,0); //反向边流量初始为零,如果走反向边费用正好和原边抵消 } int spfa(int s,int t) { int i,u,v; queue<int>q; q.push(s); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); for(i=s;i<=t;i++) dis[i]=inf; dis[s]=0; while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u];i!=-1;i=e[i].next) { v=e[i].v; if(e[i].f&&dis[v]>dis[u]+e[i].c) //找到一条最小费用流 { dis[v]=dis[u]+e[i].c; pre[v]=i; //记录路径 if(!vis[v]) { vis[v]=1; q.push(v); } } } vis[u]=0; } if(dis[t]!=inf) return 1; return 0; } void solve(int s,int t) { int ans=0,i,j; int flow=0,cost=0; //总流量、总费用 while(spfa(s,t)) { int minf=inf; for(i=pre[t];i!=-1;i=pre[e[i].u]) { if(e[i].f<minf) minf=e[i].f; } flow+=minf; //该条路径的流量 for(i=pre[t];i!=-1;i=pre[e[i].u]) { j=i^1; e[i].f-=minf; e[j].f+=minf; } cost+=dis[t]*minf; //流量乘最小费用 } printf("%d\n",cost); } int main() { int i,u,v,c,n,m; while(scanf("%d%d",&n,&m)!=-1) { t=0; memset(head,-1,sizeof(head)); for(i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&c); add(u,v,c,1); add(v,u,c,1); //无向边,费用为长度,流量为1(只能通过一次) } //往返的两条线路可以看成是从源点到汇点的两条线路, //所以只要从附加源点向源点连一条容量为2的边和从汇点向附加汇点连一条容量为2的边就可以限线路为两条. add(0,1,0,2); add(n,n+1,0,2); solve(0,n+1); } return 0; }
poj 2135 Farm Tour (最小费用最大流模板),布布扣,bubuko.com
poj 2135 Farm Tour (最小费用最大流模板)
标签:des style blog http color os io strong
原文地址:http://blog.csdn.net/u011721440/article/details/38533219