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 }
代码君

 

你可能感兴趣的:(design)