zoukankan      html  css  js  c++  java
  • 最小费用最大流(luogu P3381 【模板】最小费用最大流)

    题目链接

    题目描述

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

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    4 5 4 3
    4 2 30 2
    4 3 20 3
    2 3 20 1
    2 1 30 9
    1 3 40 5
    输出样例#1: 
    50 280

    费用流模板:

    在最大流的前提下,费用最小。由EK算法扩展。EK每次用bfs增广,把bfs改成spfa找到一条花费最小的路径即可,然后拿这条路去优化答案。

    不会EK的先去拿EK写道最大流,不会spfa的拿spfa写道最短路径在往下看。

    然后建边的时候反向弧的费用为正向弧的相反数,走反向弧相当于不走这一段边,那么最短路径部分当然要消除这一段的影响。

    AC代码

     1 #include <bits/stdc++.h>
     2 
     3 
     4 using namespace std;
     5 const int MAXN = 5010;
     6 const int MAXM = 50010;
     7 const int INF = 0x7FFFFFFF;
     8 
     9 int n, m, first[MAXN], s, t, sign;
    10 
    11 int max_flow, min_cost;
    12 
    13 struct Edge {
    14     int to, cap, cost, next;
    15 } edge[MAXM * 2];
    16 
    17 inline void init() {
    18     for(int i = 0; i <= n; i++ ) {
    19         first[i] = -1;
    20     }
    21     sign = 0;
    22 }
    23 
    24 inline void add_edge(int u, int v, int cap, int cost) {
    25     edge[sign].to = v, edge[sign].cap = cap, edge[sign].cost = cost;
    26     edge[sign].next = first[u], first[u] = sign ++;
    27     edge[sign].to = u, edge[sign].cap = 0, edge[sign].cost = -cost;
    28     edge[sign].next = first[v], first[v] = sign ++;
    29 }
    30 
    31 int dist[MAXN], inq[MAXN], pre[MAXN], incf[MAXN];
    32 
    33 bool spfa(int s, int t) {
    34     for(int i = 1; i <= n ; i++ ) {
    35         dist[i] = INF, inq[i] = 0;
    36     }
    37     queue<int>que;
    38     que.push(s), inq[s] = 1, dist[s] = 0;
    39     incf[s] = 0x3f3f3f3f;
    40     while(!que.empty()) {
    41         int now = que.front();
    42         que.pop();
    43         inq[now] = 0;
    44         for(int i = first[now]; ~i; i = edge[i].next) {
    45             int to = edge[i].to, cap = edge[i].cap, cost = edge[i].cost;
    46             if(cap > 0 && dist[to] > dist[now] + cost) {
    47                 dist[to] = dist[now] + cost;
    48                 incf[to] = min(incf[now], cap);
    49                 pre[to] = i;
    50                 if(!inq[to]) {
    51                     que.push(to);
    52                     inq[to] = 1;
    53                 }
    54             }
    55         }
    56     }
    57     return dist[t] != INF;
    58 }
    59 
    60 void update(int s, int t) {
    61     int x = t;
    62     while(x != s) {
    63         int pos = pre[x];
    64         edge[pos].cap -= incf[t];
    65         edge[pos ^ 1].cap += incf[t];
    66         x = edge[pos ^ 1].to;
    67     }
    68     max_flow += incf[t];
    69     min_cost += dist[t] * incf[t];
    70 }
    71 
    72 void minCostMaxFlow(int s, int t) {
    73     while(spfa(s, t)) {
    74         update(s, t);
    75     }
    76 }
    77 
    78 int main()
    79 {
    80     while(~scanf("%d %d %d %d", &n, &m, &s, &t)) {
    81         init();
    82         for(int i = 1; i <= m; i++ ) {
    83             int u, v, cap, cost;
    84             scanf("%d %d %d %d", &u, &v, &cap, &cost);
    85             add_edge(u, v, cap, cost);
    86         }
    87         max_flow = min_cost = 0;
    88         minCostMaxFlow(s, t);
    89         printf("%d %d
    ", max_flow, min_cost);
    90     }
    91 
    92     return 0;
    93 }
  • 相关阅读:
    PHP+AJAX 验证码验证用户登录
    2014-05-09 总结
    2014-05-08 总结(补充)
    2014-05-08 总结
    2014-05-07 总结
    14-6-2
    php
    5-23
    PHP
    5-22
  • 原文地址:https://www.cnblogs.com/Q1143316492/p/8972011.html
Copyright © 2011-2022 走看看