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

题意:给定一个有向图,让你找出若干个图,使得每个点恰好属于一个圈,并且总的权和最小。

析:每个点都有唯一的一个圈,也就是说每一点都有唯一的后继,那么我们就可以转换成求一个图的最小权的最佳完全匹配,可以用最小费用流来求,

先把每个结点拆成两个点,假设是x,y,然后建立一个源点,向每个点的x连一条容量为1的边,建立一个汇点,每个点的y向汇点连一条容量为1的边,

每条边u,v,也连接一条容量为1,费用为权值的边,最小求一个最小费用流即可。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-5;
const int maxn = 2000 + 10;
const int mod = 1e6;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
  return r >= 0 && r < n && c >= 0 && c < m;
}
struct Edge{
  int from, to, cap, flow;
  LL cost;
};

struct MCMF{
  int n, m;
  vector<Edge> edges;
  vector<int> G[maxn];
  int inq[maxn];
  LL d[maxn];
  int p[maxn];
  int a[maxn];

  void init(int n){
    this->n = n;
    for(int i = 0; i < n; ++i)  G[i].clear();
    edges.clear();
  }

  void addEdge(int from, int to, int cap, LL cost){
    edges.push_back((Edge){from, to, cap, 0, cost});
    edges.push_back((Edge){to, from, 0, 0, -cost});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BellmanFord(int s, int t, int &flow, LL &cost){
    for(int i = 0; i < n; ++i)  d[i] = INF;
    memset(inq, 0, sizeof inq);
    d[s] = 0;  inq[s] = 1;  p[s] = 0;   a[s] = INF;

    queue<int> q;
    q.push(s);
    while(!q.empty()){
      int u = q.front();  q.pop();
      inq[u] = 0;
      for(int i = 0; i < G[u].size(); ++i){
        Edge &e = edges[G[u][i]];
        if(e.cap > e.flow && d[e.to] > d[u] + e.cost){
          d[e.to] = d[u] + e.cost;
          p[e.to] = G[u][i];
          a[e.to] = min(a[u], e.cap-e.flow);
          if(!inq[e.to])  q.push(e.to),  inq[e.to] = 1;
        }
      }
    }
    if(d[t] == INF)  return false;
    flow += a[t];
    cost += d[t] * a[t];
    int u = t;
    while(u != s){
      edges[p[u]].flow += a[t];
      edges[p[u]^1].flow -= a[t];
      u = edges[p[u]].from;
    }
    return true;
  }

  int minCost(int s, int t, LL &cost){
    int flow = 0;  cost = 0;
    while(BellmanFord(s, t, flow, cost));
    return flow;
  }
};
MCMF mcmf;

int main(){
  while(scanf("%d", &n) == 1 && n){
    mcmf.init(n+n+2);
    int v;  LL val;
    int s = 0, t = n+n+1;
    for(int i = 1; i <= n; ++i){
     // mcmf.addEdge(i, i+n, 1, 0);
      mcmf.addEdge(s, i, 1, 0);
      mcmf.addEdge(i+n, t, 1, 0);
      while(scanf("%d", &v) == 1 && v){
        scanf("%lld", &val);
        mcmf.addEdge(i, v+n, 1, val);
      }
    }

    LL ans;
    if(mcmf.minCost(s, t, ans) == n)  printf("%lld\n", ans);
    else  printf("N\n");
  }
  return 0;
}
时间: 2024-12-10 15:57:52

UVa 1349 Optimal Bus Route Design (最佳完美匹配)的相关文章

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

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 最优公交路线(最小费用流)

题意:给若干景点,每个景点有若干单向边到达其他景点,要求规划一下公交路线,使得每个景点有车可达,并且每个景点只能有1车经过1次,公车必须走环形回到出发点(出发点走2次).问是否存在这样的线路?若存在就给出所有公交车需要走过的路的长度,要求长度尽量小. 分析:这超级难发现是网络流来做的.要将每个点归结到某个环上,那么环上的点都是只有1个前驱,1个后继.如果1个前驱配1个后继,就是匹配问题了.但是这样的匹配有点混杂,所以要拆点,将1个点拆成2个,分别处于X和Y集中,然后根据有向边建图.成了带权二分图

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 11383 少林决胜(二分图最佳完美匹配)

https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数col(i),使得对于任意格子(i,j),w(i,j)<=row(i)+col(j).所有的row(i)和col(i)只和应尽量小. 思路: 利用二分图最佳完美匹配当中的l(x)+l(y)>=w(i,j),直接用KM算法即可. 1 #include<iostream> 2 #inclu

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 = 10000000

uvalive 3353 Optimal Bus Route Design

题意: 给出n个点,以及每个点到其他点的有向距离,要求设计线路使得每一个点都在一个环中,如果设计的线路拥有最小值,那么这个线路就是可选的.输出这个最小值或者说明最小线路不存在. 思路: 在DAG的最小路径覆盖中,找到的最大匹配数实际是非终点的点的最大数量(每一个匹配对应一个起点),点数减去这个数量就是终点的最少数量,一个终点对应一条路径,所以这个路径覆盖是最小的. 这个题要求每一个点都在一个环中,也就是说找到一个设计线路的方案使之不存在DAG,那么自然就没有终点存在,也就意味着每一个点都可以作为