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

    https://www.luogu.org/problem/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
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<queue>
     4 #define mem(a, b) memset(a, b, sizeof(a))
     5 using namespace std;
     6 const int MAXN = 1e5 + 10;
     7 const int inf = 0x3f3f3f3f;
     8 
     9 int n, m, st, ed;//点数 边数 源点 汇点
    10 int vis[MAXN], dis[MAXN], flow[MAXN];//源点到i点的花费和流量
    11 int pre[MAXN];//每个点的前驱
    12 int last[MAXN]; //每个点连的前一条边
    13 int mincost, maxflow; 
    14 queue<int> Q;
    15 
    16 struct Edge
    17 {
    18     int to, next, flow, dis;//费用作为 dis 来跑最短路 
    19 }edge[MAXN];
    20 int head[MAXN], cnt;
    21 
    22 void add(int a, int b, int c, int d) //要用到 ^ 操作 所以边从 0 开始 
    23 {
    24     edge[++ cnt].to = b;
    25     edge[cnt].next = head[a];
    26     edge[cnt].flow = c;
    27     edge[cnt].dis = d;
    28     head[a] = cnt;
    29 }
    30 
    31 bool spfa(int st, int ed)
    32 {
    33     mem(dis, inf), mem(flow, inf), mem(vis, 0);//找到最大流以及最短路(最少费用) 
    34     Q.push(st);
    35     vis[st] = 1;
    36     dis[st] = 0;
    37     pre[ed] = -1;
    38     while(!Q.empty())
    39     {
    40         int now = Q.front();
    41         Q.pop();
    42         vis[now] = 0;
    43         for(int i = head[now]; i != -1; i = edge[i].next)
    44         {
    45             if(edge[i].flow > 0 && dis[edge[i].to] > dis[now] + edge[i].dis)
    46             {
    47                 dis[edge[i].to] = dis[now] + edge[i].dis;
    48                 pre[edge[i].to] = now;//记录更新后的新前驱 
    49                 last[edge[i].to] = i;//记录更新后的新的前一条边 为了回溯来更新边的流量 
    50                 flow[edge[i].to] = min(flow[now], edge[i].flow);//找出最大流 
    51                 if(!vis[edge[i].to])
    52                 {
    53                     vis[edge[i].to] = 1;
    54                     Q.push(edge[i].to);
    55                 }
    56             }
    57         }
    58     }
    59     return pre[ed] != -1;
    60 }
    61 
    62 void min_cost_max_flow()
    63 {
    64     while(spfa(st, ed))
    65     {
    66         int now = ed;
    67         maxflow += flow[ed];
    68         mincost += flow[ed] * dis[ed];
    69         while(now != st)//从汇点回溯更新边剩下的流量
    70         {
    71             edge[last[now]].flow -= flow[ed];
    72             edge[last[now] ^ 1].flow += flow[ed];
    73             now = pre[now];
    74         }
    75     }
    76 }
    77 
    78 int main()
    79 {
    80     mem(head, -1), cnt = -1;
    81     scanf("%d%d%d%d", &n, &m, &st, &ed);
    82     for(int i = 1; i <= m; i ++)
    83     {
    84         int a, b, c, d;
    85         scanf("%d%d%d%d", &a, &b, &c, &d); //有向边起点 终点 容量 单位费用
    86         add(a, b, c, d);
    87         add(b, a, 0, -d);//反向边流量为 0 ,花费为 负的 
    88     }
    89     min_cost_max_flow();
    90     printf("%d %d
    ", maxflow, mincost);
    91     return 0;
    92 }
    最小费用最大流模板






  • 相关阅读:
    HO引擎近况20210912
    查询超时问题的处理
    ubuntu根据关键词批量杀进程
    创建notebook适用的虚拟环境
    信赖域策略优化(Trust Region Policy Optimization, TRPO)
    强化学习(Reinforcement Learning)
    生成对抗网络(GAN与W-GAN)
    卷积神经网络CNN
    循环神经网络RNN
    PyTorch自动求导
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/11246839.html
Copyright © 2011-2022 走看看