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

     1 struct Edge{
     2     int from, to, cap, flow, cost;//出点,入点,容量,当前流量,费用(也就是权值)
     3     Edge(int u, int v, int c, int f, int w) :from(u), to(v), cap(c), flow(f), cost(w) {}
     4 };
     5 
     6 struct MCMF
     7 {
     8     int n, m;
     9     vector<Edge> edges;//保存表
    10     vector<int> G[MAXN];//保存邻接关系
    11     int inq[MAXN];//判断一个点是否在队列当中(SPFA算法当中要用)
    12     int d[MAXN];//起点到d[i]的最短路径保存值
    13     int p[MAXN];//用来记录路径,保存上一条弧
    14     int a[MAXN];//找到增广路径后的改进量
    15 
    16     void init(int n)//初始化
    17     {
    18         this->n = n;
    19         for (int i = 0; i <= n; i++)
    20             G[i].clear();
    21         edges.clear();
    22     }
    23   
    24     void AddEdge(int from, int to, int cap, int cost)//添加有向边
    25     {
    26         edges.push_back(Edge(from, to, cap, 0, cost));//正向
    27         edges.push_back(Edge(to, from, 0, 0, -cost));//反向
    28         m = edges.size();
    29         G[from].push_back(m - 2);//按照边的编号保存邻接关系
    30         G[to].push_back(m - 1);
    31     }
    32 
    33     bool BellmanFord(int s, int t, int& flow, long long& cost)//最短路径算法
    34     {
    35         for (int i = 0; i <= n; i++)
    36             d[i] = INT_MAX;
    37         memset(inq, 0, sizeof(inq));
    38         d[s] = 0;
    39         inq[s] = 1;
    40         p[s] = 0;
    41         a[s] = INT_MAX;
    42 
    43         queue<int> Q;
    44         Q.push(s);
    45         while (!Q.empty())
    46         {
    47             int u = Q.front();
    48             Q.pop();
    49             inq[u] = 0;
    50             for (int i = 0; i < G[u].size(); i++)
    51             {
    52                 Edge& e = edges[G[u][i]];
    53                 if (e.cap > e.flow&&d[e.to] > d[u] + e.cost)//寻找满足容量大于流量的可松弛边
    54                 {
    55                     d[e.to] = d[u] + e.cost;
    56                     p[e.to] = G[u][i];
    57                     a[e.to] = min(a[u], e.cap - e.flow);
    58                     if (!inq[e.to])//是否在队列当中
    59                     {
    60                         Q.push(e.to);
    61                         inq[e.to] = 1;
    62                     }
    63                 }
    64             }
    65         }
    66         if (d[t] == INT_MAX)//如果d[t]没有被更新,相当于没找到增广路径,则没有最大流也没有最小费用
    67             return false;
    68         flow += a[t];//更新最大流
    69         cost += (long long)d[t] * (long long)a[t];//单位流量乘以单位路径长度用来计算消耗
    70         for (int u = t; u != s; u = edges[p[u]].from)//通过使用p[]保存的上一个边的值来对刚刚找到的增广路径上面的流量进行更新
    71         {
    72             edges[p[u]].flow += a[t];//正向变更新
    73             edges[p[u] ^ 1].flow -= a[t];//反向变更新(用位运算实现的)
    74         }
    75         return true;
    76     }
    77 
    78     int MincostMaxflow(int s, int t, long long& cost)//计算从s到t的最小消耗cost,返回最大流
    79     {
    80         int flow = 0;
    81         cost = 0;
    82         while (BellmanFord(s, t, flow, cost));//不断寻找最短增广路径,直到找不到为止
    83         return flow;
    84     }
    85 };

    固定流量的最小消费

     1 struct Edge {
     2     int from, to, cap, flow, cost;
     3     Edge(int u, int v, int c, int f, int w) :from(u), to(v), cap(c), flow(f), cost(w) {}
     4 };
     5 
     6 struct MCF {
     7     int n, m;
     8     vector<Edge> edges;
     9     vector<int> G[MAXN];
    10     int inq[MAXN];         // 是否在队列中
    11     int d[MAXN];           // Bellman-Ford
    12     int p[MAXN];           // 上一条弧
    13     int a[MAXN];           // 可改进量
    14     void init(int n) {
    15         this->n = n;
    16         for (int i = 0; i < n; i++) G[i].clear();
    17         edges.clear();
    18     }
    19     void AddEdge(int from, int to, int cap, int cost) {
    20         edges.push_back(Edge(from, to, cap, 0, cost));
    21         edges.push_back(Edge(to, from, 0, 0, -cost));
    22         m = edges.size();
    23         G[from].push_back(m - 2);
    24         G[to].push_back(m - 1);
    25     }
    26     bool BellmanFord(int s, int t, int flow_limit, int& flow, int& cost) {
    27         for (int i = 0; i < n; i++) d[i] = INF;
    28         memset(inq, 0, sizeof(inq));
    29         d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
    30 
    31         queue<int> Q;
    32         Q.push(s);
    33         while (!Q.empty()) {
    34             int u = Q.front(); Q.pop();
    35             inq[u] = 0;
    36             for (int i = 0; i < G[u].size(); i++) {
    37                 Edge& e = edges[G[u][i]];
    38                 if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
    39                     d[e.to] = d[u] + e.cost;
    40                     p[e.to] = G[u][i];
    41                     a[e.to] = min(a[u], e.cap - e.flow);
    42                     if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
    43                 }
    44             }
    45         }
    46         if (d[t] == INF) return false;
    47         if (flow + a[t] > flow_limit) a[t] = flow_limit - flow;
    48         flow += a[t];
    49         cost += d[t] * a[t];
    50         for (int u = t; u != s; u = edges[p[u]].from) {
    51             edges[p[u]].flow += a[t];
    52             edges[p[u] ^ 1].flow -= a[t];
    53         }
    54         return true;
    55     }
    56     // 最小费用流(流量确定)
    57     // 需要保证初始网络中没有负权圈
    58     int MincostFlow(int s, int t, int flow_limit, int& cost) {
    59         int flow = 0; cost = 0;
    60         while (flow < flow_limit && BellmanFord(s, t, flow_limit, flow, cost));
    61         return flow;
    62     }
    63 };
  • 相关阅读:
    一个很诡异的javascript问题
    记录我开发鞋服行业供应链软件的历程<设计业务层>
    为什么要自已写报表中心
    关于系统的性能
    “时间”都去哪儿了?性能调优分析方法与案例详解
    工程师推荐软件
    终于有人把云计算、大数据和人工智能讲明白了!
    C# Dictionary 泛型字典集合(转)
    DEV中的TreeList控件应用的一个小效果实现
    推荐VS2008插件CodeRush Xpress for C#
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9567404.html
Copyright © 2011-2022 走看看