zoukankan      html  css  js  c++  java
  • 洛谷 P3381 【【模板】最小费用最大流】

    题目描述

    如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

    输入

    第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

    接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。

    输出

    一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。

    样例输入

    4 5 4 3
    4 2 30 2
    4 3 20 3
    2 3 20 1
    2 1 30 9
    1 3 40 5

    样例输出

    50 280

    555555本蒟蒻还不会zkw费用流,就先贴Edmond_Karp+SPFA和Primal_Dual的代码吧。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <vector>
      5 #include <queue>
      6 using namespace std;
      7 
      8 struct edge {
      9     int to,cap,cost,rev;
     10 };
     11 
     12 typedef pair<int,int> P;
     13 const int maxn=5000, maxm=50000, INF=0x7F7F7F7F;
     14 int n,m;
     15 vector <edge> G[maxn+1];
     16 
     17 edge make_edge(int to, int cap, int cost, int rev) {
     18     edge x;
     19     x.to=to, x.cap=cap, x.cost=cost, x.rev=rev;
     20     return x;
     21 }
     22 
     23 void add_edge(int from, int to, int cap, int cost) {
     24     G[from].push_back(make_edge(to,cap,cost,G[to].size()));
     25     G[to].push_back(make_edge(from,0,-cost,G[from].size()-1));
     26 }
     27 
     28 void init(int &s, int &t) {
     29     scanf("%d%d%d%d",&n,&m,&s,&t);
     30     for (int i=1; i<=m; i++) {
     31         int u,v,w,f;
     32         scanf("%d%d%d%d",&u,&v,&w,&f);
     33         add_edge(u,v,w,f);
     34     }
     35 }
     36 
     37 namespace EK_SPFA {
     38     int dis[maxn+1];
     39     int prev[maxn+1];
     40     int pree[maxn+1];
     41 
     42     void bfs(int s) {
     43         bool mark[maxn+1];
     44         memset(dis,0x7F,sizeof(dis));
     45         memset(prev,-1,sizeof(prev));
     46         memset(pree,-1,sizeof(pree));
     47         memset(mark,0,sizeof(mark));
     48         queue <int> q;
     49         dis[s]=0;
     50         q.push(s);
     51         while (!q.empty()) {
     52             int x=q.front();
     53             q.pop();
     54             mark[x]=false;
     55             for (int i=0; i<G[x].size(); i++) {
     56                 edge &e=G[x][i];
     57                 if (e.cap>0&&dis[x]+e.cost<dis[e.to]) {
     58                     dis[e.to]=dis[x]+e.cost;
     59                     prev[e.to]=x;
     60                     pree[e.to]=i;
     61                     if (!mark[e.to]) {
     62                         mark[e.to]=true;
     63                         q.push(e.to);
     64                     }
     65                 }
     66             }
     67         }
     68     }
     69 
     70     P min_cost_max_flow(int s, int t) {
     71         int flow=0, cost=0;
     72         for(;;) {
     73             bfs(s);
     74             if (dis[t]==INF)
     75                 return make_pair(flow,cost);
     76             int d=INF;
     77             for (int i=t; prev[i]!=-1; i=prev[i])
     78                 d=min(d,G[prev[i]][pree[i]].cap);
     79             flow+=d;
     80             cost+=d*dis[t];
     81             for (int i=t; prev[i]!=-1; i=prev[i]) {
     82                 edge &e=G[prev[i]][pree[i]];
     83                 e.cap-=d;
     84                 G[e.to][e.rev].cap+=d;
     85             }
     86         }
     87     }
     88 }
     89 
     90 namespace Primal_Dual {
     91     int dis[maxn+1];
     92     int h[maxn+1];
     93     int prev[maxn+1];
     94     int pree[maxn+1];
     95 
     96     void bfs(int s) {
     97         priority_queue <P, vector<P>, greater<P> > q;
     98         bool vis[maxn+1];
     99         memset(vis,0,sizeof(vis));
    100         memset(dis,0x7F,sizeof(dis));
    101         memset(prev,-1,sizeof(prev));
    102         memset(pree,-1,sizeof(pree));
    103         dis[s]=0;
    104         q.push(make_pair(0,s));
    105         while (!q.empty()) {
    106             int val=q.top().first, x=q.top().second;
    107             q.pop();
    108             if (vis[x]) continue;
    109             vis[x]=true;
    110             for (int i=0; i<G[x].size(); i++) {
    111                 edge &e=G[x][i];
    112                 if (e.cap>0&&dis[x]+e.cost+h[x]-h[e.to]<dis[e.to]&&!vis[e.to]) {
    113                     dis[e.to]=dis[x]+e.cost+h[x]-h[e.to];
    114                     prev[e.to]=x;
    115                     pree[e.to]=i;
    116                     q.push(make_pair(dis[e.to],e.to));
    117                 }
    118             }
    119         }
    120     }
    121 
    122     P min_cost_max_flow(int s, int t) {
    123         int flow=0, cost=0;
    124         memset(h,0,sizeof(h));
    125         for(;;) {
    126             bfs(s);
    127             if (dis[t]==INF)
    128                 return make_pair(flow,cost);
    129             for (int i=1; i<=n; i++)
    130                 h[i]+=dis[i];
    131             int d=INF;
    132             for (int i=t; prev[i]!=-1; i=prev[i])
    133                 d=min(d,G[prev[i]][pree[i]].cap);
    134             flow+=d;
    135             cost+=d*h[t];
    136             for (int i=t; prev[i]!=-1; i=prev[i]) {
    137                 edge &e=G[prev[i]][pree[i]];
    138                 e.cap-=d;
    139                 G[e.to][e.rev].cap+=d;
    140             }
    141         }
    142     }
    143 }
    144 
    145 int main() {
    146     int s,t;
    147     init(s,t);
    148     P ans=Primal_Dual::min_cost_max_flow(s,t);
    149     printf("%d %d
    ",ans.first,ans.second);
    150     return 0;
    151 }
  • 相关阅读:
    C语言-if语句
    C语言-表达式
    C语言-基础
    Java for LeetCode 187 Repeated DNA Sequences
    Java for LeetCode 179 Largest Number
    Java for LeetCode 174 Dungeon Game
    Java for LeetCode 173 Binary Search Tree Iterator
    Java for LeetCode 172 Factorial Trailing Zeroes
    Java for LeetCode 171 Excel Sheet Column Number
    Java for LeetCode 169 Majority Element
  • 原文地址:https://www.cnblogs.com/tweetuzki/p/8423844.html
Copyright © 2011-2022 走看看