UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

题意:

给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈。而且这些圈所有边的权值之和最小。

分析:

每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继。

所以把每个点i拆成两个点,Xi 和 Yi ,然后求二分图最小权完美匹配(流量为n也就是满载时,就是完美匹配)。

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int maxn = 200 + 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 MFMC
 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, 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         queue<int> Q;
 46         Q.push(s);
 47         while(!Q.empty())
 48         {
 49             int u = Q.front(); Q.pop();
 50             inq[u] = 0;
 51             for(int i = 0; i < G[u].size(); ++i)
 52             {
 53                 Edge& e = edges[G[u][i]];
 54                 if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
 55                 {
 56                     d[e.to] = d[u] + e.cost;
 57                     p[e.to] = G[u][i];
 58                     a[e.to] = min(a[u], e.cap - e.flow);
 59                     if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
 60                 }
 61             }
 62         }
 63         if(d[t] == INF) return false;
 64         flow += a[t];
 65         cost += d[t] * a[t];
 66         for(int u = t; u != s; u = edges[p[u]].from)
 67         {
 68             edges[p[u]].flow += a[t];
 69             edges[p[u]^1].flow -= a[t];
 70         }
 71         return true;
 72     }
 73     //需要保证初始网络中没有负权圈
 74     int MincostMaxflow(int s, int t, int& cost)
 75     {
 76         int flow = 0; cost = 0;
 77         while(BellmanFord(s, t, flow, cost));
 78         return flow;
 79     }
 80 }g;
 81 
 82 int main()
 83 {
 84     //freopen("in.txt", "r", stdin);
 85 
 86     int n;
 87     while(scanf("%d", &n) == 1 && n)
 88     {
 89         g.Init(n*2+2);
 90         for(int i = 1; i <= n; ++i)
 91         {
 92             g.AddEdge(0, i, 1, 0);//连接源点和X的点
 93             g.AddEdge(i+n, n*2+1, 1, 0);//连接汇点和Y的点
 94         }
 95         for(int i = 1; i <= n; ++i)
 96         {
 97             int j, d;
 98             while(scanf("%d", &j) == 1 && j)
 99             {
100                 scanf("%d", &d);
101                 g.AddEdge(i, n+j, 1, d);
102             }
103         }
104         int cost, flow;
105         flow = g.MincostMaxflow(0, n*2+1, cost);
106         if(flow < n) puts("N");
107         else printf("%d\n", cost);
108     }
109 
110     return 0;
111 }
代码君

 

posted @ 2015-02-10 13:44  AOQNRMGYXLMV  阅读(355)  评论(0编辑  收藏  举报