uva1658 算法竞赛入门经典海军上将费用流

Posted lqllulu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva1658 算法竞赛入门经典海军上将费用流相关的知识,希望对你有一定的参考价值。

题意

  给出一个v(3<=v<=1000)个点e(3<=e<=10000)条边的有向加权图,求1-v的两条不相交(除了起点和终点外没有公共点)的路径,使得权和最小。

分析

 费用流的一个经典用法就是限制没有公共边边,但是这个题有个不同,这个题限制的是没有公共点。因此,我们把每个点拆出一条边来。

把2到v-1的每个结点i拆成i和i‘两个结点,中间连一条容量为1,费用为0的边。对于原图中的每一条边(a,b),连一条弧(a‘,b),容量为1,费用为权值然后求1到v的流量为2的最小费用流即可。

技术分享图片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <queue>
 6 
 7 using namespace std;
 8 const int maxn=4000+10;
 9 const int maxm=40000+10;
10 const int INF=2147480000;
11 struct MCMF{
12     int head[maxn],Next[maxm],to[maxm],from[maxm],flow[maxm],cap[maxm],cost[maxm];
13     int inq[maxn],d[maxn],p[maxn],a[maxn];
14     int n,m,s,t,sz;
15     void init(int n){
16         this->n=n;
17         sz=-1;
18         memset(head,-1,sizeof(head));
19     }
20     void add_edge(int a,int b,int ca,int co){
21         ++sz;
22         from[sz]=a;to[sz]=b;Next[sz]=head[a];head[a]=sz;
23         cap[sz]=ca;cost[sz]=co;flow[sz]=0;
24         ++sz;
25         from[sz]=b;to[sz]=a;Next[sz]=head[b];head[b]=sz;
26         cap[sz]=ca;cost[sz]=-co;flow[sz]=ca;
27     }
28     bool spfa(int s,int t,int &Flow ,long long &Cost){
29         for(int i=0;i<=n;i++)d[i]=INF;
30         queue<int>Q;
31         memset(inq,0,sizeof(inq));
32         d[s]=0;inq[s]=1;p[s]=-1;a[s]=INF;
33         Q.push(s);
34         while(!Q.empty()){
35             int u=Q.front();Q.pop();
36             inq[u]=0;
37             for(int i=head[u];i!=-1;i=Next[i]){
38                 int v=to[i];
39                 if(cap[i]>flow[i]&&d[v]>d[u]+cost[i]){
40                     d[v]=d[u]+cost[i];
41                     p[v]=i;
42                     a[v]=min(a[u],cap[i]-flow[i]);
43                     if(!inq[v]){
44                         inq[v]=1;
45                         Q.push(v);
46                     }
47                 }
48             }
49         }
50         if(d[t]==INF)return false;
51         Flow+=a[t];
52         Cost+=(long long)a[t]*(long long)d[t];
53         int u=t;
54         while(u!=s){
55             flow[p[u]]+=a[t];
56             flow[p[u]^1]-=a[t];
57             u=from[p[u]];
58         }
59         return true;
60     }
61     long long Mincost(int s,int t){
62         int Flow=0;
63         long long Cost=0;
64         while(spfa(s,t,Flow,Cost));
65         return Cost;
66     }
67 }mcmf;
68 int n,m;
69 int main(){
70     while(scanf("%d%d",&n,&m)!=EOF){
71         int a,b,c;
72         mcmf.init(2*n);
73         for(int i=2;i<n;i++){
74             mcmf.add_edge(i,i+n,1,0);
75         }
76         mcmf.add_edge(1,n+1,2,0);
77         mcmf.add_edge(n,2*n,2,0);
78         for(int i=1;i<=m;i++){
79             scanf("%d%d%d",&a,&b,&c);
80             mcmf.add_edge(a+n,b,1,c);
81         }
82         int ans=mcmf.Mincost(1,2*n);
83         cout<<ans<<endl;
84     }
85 return 0;
86 }
View Code

 

 

以上是关于uva1658 算法竞赛入门经典海军上将费用流的主要内容,如果未能解决你的问题,请参考以下文章

UVA1658 Admiral 拆点法解决结点容量(路径不能有公共点,容量为1的时候) 最小费用最大流

UVa1658 Admiral (拆点法,最小费用流)

UVa 1658 - Admiral(最小费用最大流 + 拆点)

UVA 1658 - Admiral (拆点+最小费用流)

UVa 1658,Admiral (拆点+限制最小费用流)

uva 1658 Admiral (最小费最大流)