• UVa 1658


    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4533

    题意:

    给出一个v(3≤v≤1000)个点e(3≤e≤10000)条边的有向加权图,
    求1~v的两条不相交(除了起点和终点外没有公共点)的路径,使得权和最小。

    分析:

    把2到v-1的每个结点i拆成i和i'两个结点,中间连一条容量为1,费用为0的边,然后求1到v的流量为2的最小费用流即可。
    本题的拆点法是解决结点容量的通用方法。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 using namespace std;
     6 
     7 /// 结点下标从0开始,注意maxn
     8 struct MCMF {
     9     static const int maxn = 1000 * 2 + 5;
    10     static const int INF = 0x3f3f3f3f;
    11     struct Edge {
    12         int from, to, cap, flow, cost;
    13     };
    14 
    15     int n, m;
    16     vector<Edge> edges;
    17     vector<int> G[maxn];
    18     int inq[maxn]; // 是否在队列中
    19     int d[maxn]; // Bellman-Ford
    20     int p[maxn]; // 上一条弧
    21     int a[maxn]; // 可改进量
    22 
    23     void init(int n) {
    24         this->n = n;
    25         for(int i = 0; i < n; i++) G[i].clear();
    26         edges.clear();
    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         m = edges.size();
    32         G[from].push_back(m-2);
    33         G[to].push_back(m-1);
    34     }
    35     bool BellmanFord(int s, int t, int flow_limit, int& flow, int& 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]) {
    51                         Q.push(e.to);
    52                         inq[e.to] = 1;
    53                     }
    54                 }
    55             }
    56         }
    57         if(d[t] == INF) return false;
    58         if(flow + a[t] > flow_limit) a[t] = flow_limit - flow;
    59         flow += a[t];
    60         cost += d[t] * a[t];
    61         for(int u = t; u != s; u = edges[p[u]].from) {
    62             edges[p[u]].flow += a[t];
    63             edges[p[u]^1].flow -= a[t];
    64         }
    65         return true;
    66     }
    67     // 需要保证初始网络中没有负权圈
    68     int MincostMaxflow(int s, int t, int flow_limit) {
    69         int flow = 0, cost = 0;
    70         //while(BellmanFord(s, t, flow, cost));
    71         while(flow < flow_limit && BellmanFord(s, t, flow_limit, flow, cost));
    72         return cost;
    73     }
    74 };
    75 
    76 MCMF mc;
    77 
    78 int main() {
    79     int v, e;
    80     while(~scanf("%d%d", &v, &e)) {
    81         mc.init(v*2-2);
    82         for(int i = 1; i < v-1; i++) mc.AddEdge(i, i+v-1, 1, 0);
    83         for(int a, b, c, i = 0; i < e; i++) {
    84             scanf("%d%d%d", &a, &b, &c);
    85             a = (a == 1 || a == v) ? a-1 : a+v-2;
    86             b--;
    87             mc.AddEdge(a, b, 1, c);
    88         }
    89         printf("%d
    ", mc.MincostMaxflow(0, v-1, 2));
    90     }
    91     return 0;
    92 }

    最小费用最大流模板:

     1 /// 结点下标从0开始,注意maxn
     2 struct MCMF {
     3     static const int maxn = 1e3 + 5;
     4     static const int INF = 0x3f3f3f3f;
     5     struct Edge {
     6         int from, to, cap, flow, cost;
     7     };
     8 
     9     int n, m;
    10     vector<Edge> edges;
    11     vector<int> G[maxn];
    12     int inq[maxn]; // 是否在队列中
    13     int d[maxn]; // Bellman-Ford
    14     int p[maxn]; // 上一条弧
    15     int a[maxn]; // 可改进量
    16 
    17     void init(int n) {
    18         this->n = n;
    19         for(int i = 0; i < n; i++) G[i].clear();
    20         edges.clear();
    21     }
    22     void AddEdge(int from, int to, int cap, int cost) {
    23         edges.push_back((Edge){from, to, cap, 0, cost});
    24         edges.push_back((Edge){to, from, 0, 0, -cost});
    25         m = edges.size();
    26         G[from].push_back(m-2);
    27         G[to].push_back(m-1);
    28     }
    29     bool BellmanFord(int s, int t, int& flow, int& cost) {
    30         for(int i = 0; i < n; i++) d[i] = INF;
    31         memset(inq, 0, sizeof(inq));
    32         d[s] = 0;  inq[s] = 1;  p[s] = 0;  a[s] = INF;
    33         queue<int> Q;
    34         Q.push(s);
    35         while(!Q.empty()) {
    36             int u = Q.front();  Q.pop();
    37             inq[u] = 0;
    38             for(int i = 0; i < G[u].size(); i++) {
    39                 Edge& e = edges[G[u][i]];
    40                 if(e.cap > e.flow && d[e.to] > d[u] + e.cost) {
    41                     d[e.to] = d[u] + e.cost;
    42                     p[e.to] = G[u][i];
    43                     a[e.to] = min(a[u], e.cap - e.flow);
    44                     if(!inq[e.to]) {
    45                         Q.push(e.to);
    46                         inq[e.to] = 1;
    47                     }
    48                 }
    49             }
    50         }
    51         if(d[t] == INF) return false;
    52         //if(flow + a[t] > flow_limit) a[t] = flow_limit - flow;
    53         flow += a[t];
    54         cost += d[t] * a[t];
    55         for(int u = t; u != s; u = edges[p[u]].from) {
    56             edges[p[u]].flow += a[t];
    57             edges[p[u]^1].flow -= a[t];
    58         }
    59         return true;
    60     }
    61     // 需要保证初始网络中没有负权圈
    62     int MincostMaxflow(int s, int t) {
    63         int flow = 0, cost = 0;
    64         while(BellmanFord(s, t, flow, cost));
    65         //while(flow < flow_limit && BellmanFord(s, t, flow_limit, flow, cost));
    66         return cost;
    67     }
    68 };
  • 相关阅读:
    ConcurrentHashMap 实现缓存类
    maven 时区设置&ip&jdk编译版本
    【Hutool】工具类之日期时间工具-DateUtil
    正则表达式
    kafka connector
    kafka
    debezium、kafka connector 解析 mysql binlog 到 kafak
    网络流
    斜率优化
    8.8
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9539620.html
Copyright © 2020-2023  润新知