• UVa 1658 (拆点法 最小费用流) Admiral


    题意:

    给出一个有向带权图,求从起点到终点的两条不相交路径使得权值和最小。

    分析:

    第一次听到“拆点法”这个名词。

    把除起点和终点以外的点拆成两个点i和i',然后在这两点之间连一条容量为1,费用为0的边。这样就保证了每个点最多经过一次。

    其他有向边的容量也是1

    然后求从起点到终点的流量为2(这样就保证了是两条路径)的最小费用流。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int maxn = 2000 + 10;
      6 const int INF = 1000000000;
      7 
      8 struct Edge
      9 {
     10     int from, to, cap, flow, cost;
     11     Edge(int u, int v, int c, int f, int w): from(u), to(v), cap(c), flow(f), cost(w) {}
     12 };
     13 
     14 struct MCMF
     15 {
     16     int n, m;
     17     vector<Edge> edges;
     18     vector<int> G[maxn];
     19     int inq[maxn]; //是否在队列中
     20     int d[maxn];    //Bellman-Ford
     21     int p[maxn];    //上一条弧
     22     int a[maxn];    //可改进量
     23 
     24     void Init(int n)
     25     {
     26         this->n = n;
     27         for(int i = 0; i < n; ++i) G[i].clear();
     28         edges.clear();
     29     }
     30 
     31     void AddEdge(int from, int to, int cap, int cost)
     32     {
     33         edges.push_back(Edge(from, to, cap, 0, cost));
     34         edges.push_back(Edge(to, from, 0, 0, -cost));
     35         m = edges.size();
     36         G[from].push_back(m-2);
     37         G[to].push_back(m-1);
     38     }
     39 
     40     bool BellmanFord(int s, int t, int flow_limit, int& flow, int& cost)
     41     {
     42         for(int i = 0; i < n; ++i) d[i] = INF;
     43         memset(inq, 0, sizeof(inq));
     44         d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
     45 
     46         queue<int> Q;
     47         Q.push(s);
     48         while(!Q.empty())
     49         {
     50             int u = Q.front(); Q.pop();
     51             inq[u] = 0;
     52             for(int i = 0; i < G[u].size(); ++i)
     53             {
     54                 Edge& e = edges[G[u][i]];
     55                 if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
     56                 {
     57                     d[e.to] = d[u] + e.cost;
     58                     p[e.to] = G[u][i];
     59                     a[e.to] = min(a[u], e.cap - e.flow);
     60                     if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
     61                 }
     62             }
     63         }
     64         if(d[t] == INF) return false;
     65         if(flow + a[t] > flow_limit) a[t] = flow_limit - flow;
     66         flow += a[t];
     67         cost += d[t] * a[t];
     68         for(int u = t; u != s; u = edges[p[u]].from)
     69         {
     70             edges[p[u]].flow += a[t];
     71             edges[p[u]^1].flow -= a[t];
     72         }
     73         return true;
     74     }
     75 
     76     int MincostMaxflow(int s, int t, int flow_limit, int& cost)
     77     {
     78         int flow = 0; cost = 0;
     79         while(flow < flow_limit && BellmanFord(s, t, flow_limit, flow, cost));
     80         return flow;
     81     }
     82 }g;
     83 
     84 int main()
     85 {
     86     //freopen("in.txt", "r", stdin);
     87 
     88     int n, m;
     89     while(scanf("%d%d", &n, &m) == 2 && n)
     90     {
     91         g.Init(n*2-2);
     92         //2~n-1 i和i'的编号分别为1~n-2  n~2n-3
     93         for(int i = 2; i <= n-1; ++i) g.AddEdge(i-1, n-2+i, 1, 0);
     94         for(int i = 0; i < m; ++i)
     95         {   //连接a'->b
     96             int a, b, c;
     97             scanf("%d%d%d", &a, &b, &c);
     98             if(a != 1 && a != n) a += n-2; else a--;
     99             b--;
    100             g.AddEdge(a, b, 1, c);
    101         }
    102         int cost;
    103         g.MincostMaxflow(0, n-1, 2, cost);
    104         printf("%d
    ", cost);
    105     }
    106 
    107     return 0;
    108 }
    代码君
  • 相关阅读:
    python 连接操作mysql数据库
    (转)postfix疯狂外发垃圾邮件之分析与解决
    ansible 常用方法
    用python2.7.9 写个小程序搜索某个目录下行有某关键字
    python获取文件扩展名的方法(转)
    ceph 池管理
    UVALive 5412 Street Directions
    UVALive 3231 Fair Share
    UVA 11478 Halum
    2015 Multi-University Training Contest 4 hdu 5338 ZZX and Permutations
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4282761.html
Copyright © 2020-2023  润新知