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 }

代码君

时间: 2024-10-12 03:05:14

UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design的相关文章

UVA 1349 Optimal Bus Route Design

恰好属于一个圈,那等价与每个点有唯一的前驱和后继,那么把一个点拆开,前驱作为S集和后继作为T集,然后连边,跑二分图最小权完美匹配. 二分图最大匹配的匈牙利算法还能看懂,可是最大权完美匹配KM算法又是个什么鬼啊...只会写费用流.. #include<bits/stdc++.h> using namespace std; const int maxn = 200+6; struct Edge { int v,cap,cost,nxt; }; vector<Edge> edges; #

UVA 1349 - Optimal Bus Route Design(KM完美匹配)

UVA 1349 - Optimal Bus Route Design 题目链接 题意:给定一些有向带权边,求出把这些边构造成一个个环,总权值最小 思路:由于环入度出度为1,所以可以把每个点拆成入度点和出度点,然后建图做一次二分图完美匹配即可,注意这题坑点,有重边 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std

POJ 2404 Jogging Trails(最小权完美匹配)

[题目链接] http://poj.org/problem?id=2404 [题目大意] 给出一张图,求走遍所有的路径至少一次,并且回到出发点所需要走的最短路程 [题解] 如果图中所有点为偶点,那么一定存在欧拉回路, 否则一定存在偶数个奇点,将这些奇点取出构建新图, 任意两点之间的边权威原图中两点的最短距离, 用状压DP求最小权完美匹配,加上原图所有边权和就是答案. [代码] #include <cstdio> #include <algorithm> #include <c

hdu1533 Going Home km算法解决最小权完美匹配

Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5539    Accepted Submission(s): 2907 Problem Description On a grid map there are n little men and n houses. In each unit time, every l

poj3565 Ants km算法求最小权完美匹配,浮点权值

/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求是否存在n条边,每条边恰好连一个白点,一个黑点,且所有的边不相交. 输出所有黑点连接的白点编号. 思路:最小权完美匹配. 假定有白点1(a1,b1), 2(a2,b2), 黑点3(a3,b3),4(a4,b4); 如果1(a1,b1)与3(a3,b3)相连,2(a2,b2)与4(a4,b4)相连,如

UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配

/** 题目:UVA1349 Optimal Bus Route Design 链接:https://vjudge.net/problem/UVA-1349 题意:lrj入门经典P375 给n个点(n<=100)的有向带权图,找若干个有向圈,每个点恰好属于一个圈.要求权和尽量小.注意即使(u,v) 和(v,y)都存在,他们的权值也不一定相同. 思路:拆点法+最小费用最佳完美匹配. 如果每个点都有一个唯一的后继(不同的点没有相同的后继点,且只有一个后继),那么每个点一定恰好属于一个圈. 联想到二分

LA 3353 Optimal Bus Route Design 二分匹配和有向图中的环

题意:题目给出一个有向图 , 找若干个圈,使得每个结点切好属于一个圈,并且所有圈的总长度最小 , 如果没有满足条件的就输出 'N' . 注意:1.有重边 2.如果有向边(u , v) , (v , u)都存在 , 它们的长度不一定相同. 解法: 刚看这个题目的时候,没有什么思路,知道是用二分匹配之后就更没思路了.这题的关键还是在于构图: 每个点分成入度点和出度点两个点,然后在从新建图,例如:u 分成 u1 , u2 , v 分成 v1 , v2 , 假如有 (u , v) 这条边 , 那么就变成

题解 UVA1349 【Optimal Bus Route Design】

题目链接 Solution UVA1349 Optimal Bus Route Design 题目大意:给定一个带权有向图,选出若干个简单环,使每个点含于且仅含于一个环,并使得边权和最小 分析:既然每个点仅被包含于一个简单环,那么每个点的入度与出度都为\(1\),也就是这个点有且仅有一条入(出)边.但是我们又不能贪心的去选这个点入边/出边中边权最小的一条边,这样选出来的方案可能根本不合法(不能保证每个点都有入边,可能出现一个环加上一条链之类鬼畜的情况) 那么我们回想一下在无权\(DAG\)上我们

UVa 1349 Optimal Bus Route Design (最佳完美匹配)

题意:给定一个有向图,让你找出若干个图,使得每个点恰好属于一个圈,并且总的权和最小. 析:每个点都有唯一的一个圈,也就是说每一点都有唯一的后继,那么我们就可以转换成求一个图的最小权的最佳完全匹配,可以用最小费用流来求, 先把每个结点拆成两个点,假设是x,y,然后建立一个源点,向每个点的x连一条容量为1的边,建立一个汇点,每个点的y向汇点连一条容量为1的边, 每条边u,v,也连接一条容量为1,费用为权值的边,最小求一个最小费用流即可. 代码如下: #pragma comment(linker, "