训练指南 UVALive - 3126(DAG最小路径覆盖)



layout: post
title: 训练指南 UVALive - 3126(DAG最小路径覆盖)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 二分图
- 图论
- 训练指南
- 最小路径覆盖


Taxi Cab Scheme

UVALive - 3126

题目大意:n个客人,从城市的不同位置出发,到达他们的目的地。已知每个人的出发时间hh:mm,出发地点(x1,y1)及目的地(x2,y2),要求使用最少的出租车接送乘客,使得每个顾客的要求都被执行,且每次出租车接客时需要至少提前一分钟到达乘客所在的位置。城区是网格型的,地址用(x,y)表示,出租车从(x1,y1)到(x2,y2)需要行驶|x1 - x2| + |y1 - y2|分钟。

题目分析:本题的模型是DAG上的最小路径覆盖。将每个客人视为一个节点,如果接送完顾客i后还可以继续接送顾客j,则对应DAG中的一条边i -> j。对每个节点拆点为i,i‘,如果图中存在有向边i -> j,则建边(i,j‘)。设二分图的最大匹配数为m,则结果即为n - m

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e3+50;
const ll inf=1e10;
const ll INF = 1000000000;
const double eps=1e-5;
#define bug cout<<"bbibibibbbb="<<endl;
/// 二分图最大基数匹配
struct BPM{
    int n,m;    /// 左右顶点个数
    int G[maxn][maxn]; /// 邻接表
    int left[maxn];    /// left[i]为右边第i个点的匹配点编号,-1表示不存在
    bool T[maxn];       /// T[i]为右边第i个点是否已标记

    int right[maxn];        /// 求最小覆盖用
    bool S[maxn];           /// 求最小覆盖用

    void init(int n,int m){
        this->n=n;
        this->m=m;
        memset(G,0,sizeof(G));
    }

   /* void AddEdge(int u,int v){
        G[u].push_back(v);
    }*/

    bool match(int u){
        S[u]=true;
        for(int v=0;v<m;v++){
            //int v=G[u][i];
            if(G[u][v]&&!T[v]){
                T[v]=true;
                if(left[v]==-1||match(left[v])){
                    left[v]=u;
                    right[u]=v;
                    return true;
                }
            }
        }
        return false;
    }
    /// 求最大匹配
    int solve(){
        memset(left,-1,sizeof(left));
        memset(right,-1,sizeof(right));
        int ans=0;
        for(int u=0;u<n;u++){
            memset(S,0,sizeof(S));
            memset(T,0,sizeof(T));
            if(match(u))ans++;
        }
        return ans;
    }
    /// 求最小覆盖。X和Y为最小覆盖中的点集
    int mincover(vector<int>& X,vector<int>& Y){
        int ans=solve();
        memset(S,0,sizeof(S));
        memset(T,0,sizeof(T));
        for(int u=0;u<n;u++)
            if(right[u]==-1)match(u);
        for(int u=0;u<n;u++)
            if(!S[u])X.push_back(u);
        for(int v=0;v<n;v++)
            if(T[v])Y.push_back(v);
        return ans;
    }
};
BPM solver;
int x1[maxn],yyy[maxn],x2[maxn],y2[maxn],t1[maxn],t2[maxn];
int dist(int a,int b,int c,int d){
    return abs(a-c)+abs(b-d);
}

int main(){
  int T;
  scanf("%d", &T);
  while(T--) {
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
      int h, m;
      scanf("%d:%d%d%d%d%d", &h, &m, &x1[i], &yyy[i], &x2[i], &y2[i]);
      t1[i] = h*60+m;
      t2[i] = t1[i] + dist(x1[i], yyy[i], x2[i], y2[i]);
    }
    solver.init(n, n);
    for(int i = 0; i < n; i++)
      for(int j = i+1; j < n; j++)
        if(t2[i] + dist(x2[i], y2[i], x1[j], yyy[j]) < t1[j]) solver.G[i][j] = 1; // 至少要提前1分钟到达
    printf("%d\n", n - solver.solve());
  }
  return 0;
}

原文地址:https://www.cnblogs.com/luowentao/p/10352392.html

时间: 2024-10-09 17:15:42

训练指南 UVALive - 3126(DAG最小路径覆盖)的相关文章

【LA3126 训练指南】出租车 【DAG最小路径覆盖】

题意 你在一座城市里负责一个大型活动的接待工作.明天将有m位客人从城市的不同的位置出发,到达他们各自的目的地.已知每个人的出发时间,出发地点和目的地.你的任务是用尽量少的出租车送他们,使得每次出租车接客人时,至少能提前一分钟到达他所在的位置.注意,为了满足这一条件,要么这位客人是这辆出租车接送的第一个人,要么在接送完上一个客人后,有足够的时间从上一个目的地开到这里. 为了简单起见,假定城区是网格型的,地址用坐标(x,y)表示,出租车从(x1,y1)到(x2,y2)处需要行驶|x1-x2|+|y1

uva1201 DAG 最小路径覆盖,转化为 二分图

大白例题P356 你在一座城市里负责一个大型活动的接待工作.你需要去送m个人从出发地到目的地,已知每个人的出发时间出发地点,和目的地点,你的任务是用尽量少的出租车送他们,使得每次出租车接客人,至少能提前一分钟达到他所在的位置,城市为网格 (x1,y1) ===>(x2,y2) 需要|x1-x2|+|y1-y2|分钟 题解: 本题的模型是DAG的最小路径覆盖.所谓最小路径覆盖就是在图中找尽量少的路径,使得每个结点恰好在一条路径上(话句话说,不同路径不能有公共点).单独的节点也可以作为一条路径. 本

POJ 1422 DAG最小路径覆盖

求无向图中能覆盖每个点的最小覆盖数 单独的点也算一条路径 这个还是可以扯到最大匹配数来,原因跟上面的最大独立集一样,如果某个二分图(注意不是DAG上的)的边是最大匹配边,那说明只要取两个端点只要一条边即可. 故最小覆盖数还是 顶点数-最大匹配数 根据DAG建图的时候,就是DAG有边就给对应的端点建边 #include <iostream> #include <cstdio> #include <cstring> using namespace std; int d[15

POWOJ 1739: 魔术球问题 DAG最小路径覆盖转最大流

1739: 魔术球问题 题意: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.对于给定的n,计算在n根柱子上最多能放多少个球. tags: 对大佬来说应该是很素的一道题,但某还是花了好多时间才做出来.. 一开始连建图都有点懵,然后最小路径还是新概念,最大匹配也不太懂,最大流倒是会一点. 然后要打印答案,也不

POJ1422 Air Raid 【DAG最小路径覆盖】

Air Raid Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6763   Accepted: 4034 Description Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an i

bzoj 2044 三维导弹拦截——DAG最小路径覆盖(二分图)

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2044 还以为是CDQ.发现自己不会三维以上的-- 第一问可以n^2.然后是求最长不下降子序列吗?dilworth好像不能用吧. 那就是能从自己转移到哪些状态就从自己向哪些状态连边,然后就是最小路径覆盖了.用二分图的 n-最大匹配 . 注意:没有位置的限制所以可以先按 x 排序! #include<iostream> #include<cstdio> #include<c

二分图最大匹配,最小路径覆盖,最小点覆盖,最大独立集,最小边覆盖与建图方法

转载请注明出处(别管写的好坏,码字也不容易):http://blog.csdn.net/hitwhacmer1 前言:         有自己写的,有摘的别人的,前面是摘的,也是无心整理,出错是难免的,反正我都不会证明,智人见智,别被我误导了. §1图论点.边集和二分图的相关概念和性质 点覆盖.最小点覆盖 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是"点" 覆盖了所有"边"..极小点覆盖(minimal vertex covering):本身为点覆

有向无环图(DAG)的最小路径覆盖

DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如图,其最小路径覆盖数为3.即1->3>4,2,5. 最小可相交路径覆盖:每一条路径经过的顶点可以相同.如果其最小路径覆盖数为2.即1->3->4,2->3>5. 特别的,每个点自己也可以称为是路径覆盖,只不过路径的长度是0. DAG的最小不相交路径覆盖 算法:把原图的每个点

POJ 1442 Air Raid(DAG图的最小路径覆盖)

题意: 有一个城镇,它的所有街道都是单行(即有向)的,并且每条街道都是和两个路口相连.同时已知街道不会形成回路. 可以在任意一个路口放置一个伞兵,这个伞兵会顺着街道走,依次经过若干个路口. 问最少需要投放几个伞兵,使得每个路口都被伞兵拜访过.并且要满足每个路口只能被一个伞兵拜访过. 思路: 裸DAG图的最小路径覆盖. DAG图的最小路径覆盖数 = 节点数 - 二分图最大匹配 代码: vector<int> graph[125]; int cx[125],cy[125]; bool bmask[