UVA 1658 Admiral(拆点+最小费用流)
来源:互联网 发布:u盘数据突然没有了 编辑:程序博客网 时间:2024/04/29 19:05
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4533
思路:要求求两条不相交路径(除起点与终点),单纯从容量限制考虑并不能对经过点作出限制。则将点2--n-1的每个点i,拆成i与i',i与i'连一条容量为1,费用为0的边,对于每一条边<x,y>,将其化为点x'与y连边,容量为1,费用为其边权值(若x为1,则直接相连,x为n时,由于要求从1-->n,可忽略改边)。则此时走两条不相交路径最小权值即为最大流量为2时的最小费用(由于边<i,i'>容量为1,不可能出现相交)。
最大流量为2时费用:(1)增广时判断是否flow+a[t]>=k(k=2),若满足,则只增广k-flow,并终止增广。(2)设置两虚拟节点0、2*n,从0向1连边,容量为2,费用为0,;从n向2*n连边,容量为2,费用为0,,此时只需求0-->2*n的最小费用流即可(最大流量只能<=2,而由存在解,则最大流量为2)。
#include<cstdio>#include<queue>#include<vector>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=4000+50;const int INF=0x3f3f3f3f;struct Edge{ int from,to,cap,flow,cost;};struct MCMF{ int n,m,s,t,flag; vector<Edge> edges; vector<int> G[maxn]; int inq[maxn],d[maxn]; int p[maxn],a[maxn]; void init(int n) { flag=0; this->n=n; for(int i=0; i<n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,int cost) { edges.push_back((Edge){from,to,cap,0,cost}); edges.push_back((Edge){to,from,0,0,-cost}); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int s,int t,int k,int &flow,int &cost) { for(int i=0; i<n; i++) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0,inq[s]=1,p[s]=0,a[s]=INF; queue<int> Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(),inq[u]=0; for(int i=0; i<G[u].size(); i++) { Edge &e=edges[G[u][i]]; if(e.cap>e.flow&&d[e.to]>d[u]+e.cost) { d[e.to]=d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]=min(a[u],e.cap-e.flow); if(!inq[e.to]) { Q.push(e.to); inq[e.to]=1; } } } } if(d[t]==INF) return false; if(flow+a[t]>=k) {a[t]=k-flow;flag=1;} flow+=a[t]; cost+=d[t]*a[t]; if(flag) return false; int u=t; while(u!=s) { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } int Mincost(int s,int t,int k) { int flow=0,cost=0; while(BellmanFord(s,t,k,flow,cost)); return cost; }};MCMF G;int n,m;int main(){ while(scanf("%d%d",&n,&m)!=EOF) { G.init(2*n+1); for(int i=2; i<=n-1; i++) G.AddEdge(i,i+n,1,0); for(int i=0; i<m; i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); if(x==n) continue; if(x==1) G.AddEdge(x,y,1,w); else G.AddEdge(x+n,y,1,w); } printf("%d\n",G.Mincost(1,n,2)); } return 0;}
0 0
- UVA 1658 - Admiral (拆点+最小费用流)
- UVA 1658 Admiral(拆点+最小费用流)
- UVA 1658 Admiral [费用流] [拆点]
- UVA 1658Admiral(拆点+费用流)
- UVA 1658 Admiral (最小费用流)
- UVa 1658 Admiral (最小费用最大流、拆点法)
- UVA1658 - Admiral(最小费用最大流+拆点)
- UVa1658 Admiral(拆点法+最小费用流)
- uva 1658 Admiral (最小费最大流)
- uva 1658 Admiral 最小费最大流
- uva1658 Admiral 最小费用最大流
- 最小费用最大流--uva1658 Admiral
- UVA 1658 Admiral——拆点法+最小费最大流
- 最小费用流: uva 1658
- LA6266 Admiral 费用流
- UVALive - 6266 Admiral 费用流
- UVa 1658 Admiral
- uva 1658 Admiral
- 论文笔记之---DenseCap:Fully Convolutional Localization Networks for Dense Captioning
- Mybatis源码笔记一
- ActionMode 就记这么一点,不能更多了
- 递推和递归二分——奇怪的电梯
- 《Effective Java》中的建议
- UVA 1658 Admiral(拆点+最小费用流)
- Java基础编程
- 【Android develop】【学习笔记003】在界面中显示及输入文本信息
- 数据结构实验之链表九:双向链表
- #HDU4390#表达式计数
- 高精度——高精度减法
- js基础笔记
- Json 和 Jsonlib 的使用
- 我的视频课程,欢迎大家关注学习!