zoukankan      html  css  js  c++  java
  • 网络流24题——餐巾计划问题(有源汇的最小费用可行流)

    链接:https://www.oj.swust.edu.cn/oj/problem/show/1745

    分析:

           我的想法是,首先每天的餐巾数有限制,所以先拆点,从Xi向Yi连一条容量和下界均为ri的边,Xi看作每天得到的新餐巾(洗好的+新买的),从s向Xi连一条容量为inf,费用为p的边;再从Xi向X(i+m)连一条容量为inf,费用为f的边,向X(i+n)连容量为inf,费用为s的边,还有不洗的那些,直接留到下一天,就是从Xi到X(i+1)连一条容量为inf,费用为0的边(最后一天的直接连到t上),然后求这个图的最小费用可行流。

           带下界的最小费用可行流求法:先从t到s连容量为inf,费用为0的边,变成无源无汇的图,增加附加源汇S、T,然后对于每一条从u到v下界为b上界为c费用为w的边,拆成u到T容量为b、费用为w的边和S到v容量为b费用为0的边,再把u到v的边容量改为c-b,求S-T最小费用最大流即为所求,当且仅当附加边均满流时问题有解。

            题解是二分图。。比我的做法简单。。

    我的做法:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<queue>
     6 #include<stack>
     7 using namespace std;
     8 typedef long long ll;
     9 const int maxn=5e3+5,INF=1e9;
    10 struct Edge{
    11     int from,to,cap,flow,cost;
    12     Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){}
    13 };
    14 struct MCMF{
    15     int n,s,t;
    16     vector<Edge> edges;
    17     vector<int> G[maxn];
    18     int inq[maxn],d[maxn],p[maxn],a[maxn];
    19     ll flow,cost;
    20     void init(int n){
    21         this->n=n;
    22         flow=0,cost=0;
    23         for(int i=0;i<n;i++)G[i].clear();
    24         edges.clear();
    25     }
    26 
    27     void AddEdge(int from,int to,int cap,int cost){
    28         edges.push_back(Edge(from,to,cap,0,cost));
    29         edges.push_back(Edge(to,from,0,0,-cost));
    30         G[from].push_back(edges.size()-2);
    31         G[to].push_back(edges.size()-1);
    32     }
    33 
    34     bool spfa(int s,int t){
    35         for(int i=0;i<n;i++)d[i]=INF;
    36         memset(inq,0,sizeof(inq));
    37         d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;
    38         queue<int>Q;
    39         Q.push(s);
    40         while(!Q.empty()){
    41             int u=Q.front();Q.pop();
    42             inq[u]=0;
    43             for(int i=0;i<G[u].size();i++){
    44                 Edge& e=edges[G[u][i]];
    45                 if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){
    46                     d[e.to]=d[u]+e.cost;
    47                     p[e.to]=G[u][i];
    48                     a[e.to]=min(a[u],e.cap-e.flow);
    49                     if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;}
    50                 }
    51             }
    52         }
    53         if(d[t]==INF)return false;
    54         flow+=a[t];cost+=d[t]*a[t];
    55         int u=t;
    56         while(u!=s){
    57             edges[p[u]].flow+=a[t];
    58             edges[p[u]^1].flow-=a[t];
    59             u=edges[p[u]].from;
    60         }
    61         return true;
    62     }
    63     ll Mincost(int s,int t){
    64         while(spfa(s,t));
    65         return cost;
    66     }
    67 }mcmf;
    68 
    69 int N,p,m,f,n,s,r[maxn];
    70 void add(int k,int r){
    71     mcmf.AddEdge(0,k,INF,p);
    72     mcmf.AddEdge(2*N+2,k+N,r,0);
    73     mcmf.AddEdge(k,2*N+3,r,0);
    74     if(k+1<=N)mcmf.AddEdge(k+N,k+1+N,INF,0);
    75     if(k+m<=N)mcmf.AddEdge(k+N,k+m,INF,f);
    76     if(k+n<=N)mcmf.AddEdge(k+N,k+n,INF,s);
    77 }
    78 int main(){
    79 //    freopen("e:\in.txt","r",stdin);
    80     scanf("%d%d%d%d%d%d",&N,&p,&m,&f,&n,&s);
    81     for(int i=1;i<=N;i++)scanf("%d",&r[i]);
    82     mcmf.init(2*N+4);
    83     mcmf.AddEdge(2*N,2*N+1,INF,0);
    84     mcmf.AddEdge(2*N+1,0,INF,0);
    85     for(int i=1;i<=N;i++){
    86         add(i,r[i]);
    87     }
    88     printf("%lld
    ",mcmf.Mincost(2*N+2,2*N+3));
    89     return 0;
    90 }

    二分图做法:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<queue>
     6 #include<stack>
     7 using namespace std;
     8 typedef long long ll;
     9 const int maxn=5e3+5,INF=1e9;
    10 struct Edge{
    11     int from,to,cap,flow,cost;
    12     Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){}
    13 };
    14 struct MCMF{
    15     int n,s,t;
    16     ll flow,cost;
    17     vector<Edge> edges;
    18     vector<int> G[maxn];
    19     int inq[maxn],d[maxn],p[maxn],a[maxn];
    20 
    21     void init(int n){
    22         flow=0,cost=0;
    23         this->n=n;
    24         for(int i=0;i<n;i++)G[i].clear();
    25         edges.clear();
    26     }
    27 
    28     void AddEdge(int from,int to,int cap,int cost){
    29         edges.push_back(Edge(from,to,cap,0,cost));
    30         edges.push_back(Edge(to,from,0,0,-cost));
    31         G[from].push_back(edges.size()-2);
    32         G[to].push_back(edges.size()-1);
    33     }
    34 
    35     bool spfa(int s,int t,ll &flow,ll &cost){
    36         for(int i=0;i<n;i++)d[i]=INF;
    37         memset(inq,0,sizeof(inq));
    38         d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;
    39         queue<int>Q;
    40         Q.push(s);
    41         while(!Q.empty()){
    42             int u=Q.front();Q.pop();
    43             inq[u]=0;
    44             for(int i=0;i<G[u].size();i++){
    45                 Edge& e=edges[G[u][i]];
    46                 if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){
    47                     d[e.to]=d[u]+e.cost;
    48                     p[e.to]=G[u][i];
    49                     a[e.to]=min(a[u],e.cap-e.flow);
    50                     if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;}
    51                 }
    52             }
    53         }
    54         if(d[t]==INF)return false;
    55         flow+=a[t];cost+=d[t]*a[t];
    56         int u=t;
    57         while(u!=s){
    58             edges[p[u]].flow+=a[t];
    59             edges[p[u]^1].flow-=a[t];
    60             u=edges[p[u]].from;
    61         }
    62         return true;
    63     }
    64     ll Mincost(int s,int t){
    65         while(spfa(s,t,flow,cost));
    66         return cost;
    67     }
    68 }isap;
    69 
    70 int N,p,m,f,n,s,r[maxn];
    71 void add(int k,int r){
    72     isap.AddEdge(0,k,r,0);
    73     isap.AddEdge(0,k+N,INF,p);
    74     isap.AddEdge(k+N,2*N+1,r,0);
    75     if(k+1<=N)isap.AddEdge(k,k+1,INF,0);
    76     if(k+m<=N)isap.AddEdge(k,k+m+N,INF,f);
    77     if(k+n<=N)isap.AddEdge(k,k+n+N,INF,s);
    78 }
    79 int main(){
    80 //    freopen("e:\in.txt","r",stdin);
    81     scanf("%d%d%d%d%d%d",&N,&p,&m,&f,&n,&s);
    82     isap.init(2*N+2);
    83     int r;
    84     for(int i=1;i<=N;i++){
    85         scanf("%d",&r);
    86         add(i,r);
    87     }
    88     printf("%lld
    ",isap.Mincost(0,2*N+1));
    89     return 0;
    90 }
  • 相关阅读:
    install kde in ubuntu
    Upgrade to or Install Cinnamon 2.4 in Ubuntu
    enjoy dollar vs cash dollar
    opencv linux
    高频交易都有哪些著名的算法
    wpf
    opencv mat flags含义
    gphoto2 canon eos450d
    gphoto2
    task optimization之superglue分析
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7448240.html
Copyright © 2011-2022 走看看