首页 > 代码库 > 最小费用最大流
最小费用最大流
解释:每次在s-t之间找出费用最小的一条路径即单源最短路,如果t点不再被访问到,则算法终止。否则,按着最短路径找出最小剩余容量c,最大流量加上c,再更新最短路径上的边,前向弧减去c,反向弧加上c,并且造一条逆向的费用边,最小费用加上每条边的花销,每条边的花销=单位费用*c。
最小费用最大流既能求最小费用,又能得出最大流,是更为一般的模型。
模板:
#define maxn 20005 struct { int v,w,c,next,re; //re记录逆边的下标,c是费用,w是流量 } e[maxn]; int n,m,cnt; int head[maxn],que[maxn], pre[maxn], dis[maxn]; bool vis[maxn]; void addEdge(int u, int v, int w, int c) { e[cnt].v=v,e[cnt].w=w,e[cnt].c=c; e[cnt].next=head[u]; e[cnt].re=cnt+1,head[u]=cnt++; e[cnt].v=u,e[cnt].w=0,e[cnt].c=-c; e[cnt].next=head[v]; e[cnt].re=cnt-1,head[v]=cnt++; } bool spfa() { int i, l = 0, r = 1; for(i = 0; i <= n; i ++) dis[i] = INF,vis[i] = false; dis[0]=0,que[0]=0,vis[0]=true; while(l<r) { int u = que[l ++]; for(i=head[u];i!=-1;i=e[i].next) { int v = e[i].v; if(e[i].w&&dis[v]>dis[u]+e[i].c) { dis[v] = dis[u] + e[i].c; pre[v] = i; if(!vis[v]) { vis[v] = true; que[r ++] = v; } } } vis[u] = false; } if(dis[n] == INF) return false; return true; } int change() { int i, p,sum=INF,ans=0; for(i=n;i!=0;i=e[e[p].re].v) { p=pre[i]; sum=min(sum,e[p].w); } for(i=n;i!=0;i=e[e[p].re].v) { p=pre[i]; e[p].w-=sum; e[e[p].re].w+=sum; ans+=sum*e[p].c;//c记录的为单位流量费用,必须得乘以流量。 } return ans; } int dinic() { int sum=0; while(spfa()) sum+=change(); return sum; }
最小费用最大流
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。