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

大白例题P356 你在一座城市里负责一个大型活动的接待工作。你需要去送m个人从出发地到目的地,已知每个人的出发时间出发地点,和目的地点,你的任务是用尽量少的出租车送他们,使得每次出租车接客人,至少能提前一分钟达到他所在的位置,城市为网格 (x1,y1) ===>(x2,y2) 需要|x1-x2|+|y1-y2|分钟

题解:

本题的模型是DAG的最小路径覆盖。所谓最小路径覆盖就是在图中找尽量少的路径,使得每个结点恰好在一条路径上(话句话说,不同路径不能有公共点)。单独的节点也可以作为一条路径。

本题中“时间” 是一个天然的序, 因此可以构图如下: 每个客人是一个节点,如果同一个出租车在接完客人u以后来得及接客人v,离岸边u_>v, 不难发现是一个DAG, 并且它的最小 路径覆盖就是本题的答案。

大白书 P357讲解:DAG最小路径覆盖的解法把所有节点i 拆成 X 节点i  和Y 节点i‘ , 如果图G中存在有向边 i->j,则在二分图中引入i->j‘, 设最大匹配数位m,则结果就是 n-m.

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <vector>
 5 #include <cstdio>
 6 using namespace std;
 7 const int maxn =505;
 8 struct person{
 9    int time;
10    int sx,sy,tx,ty;
11 }P[maxn];
12 struct BPM{
13      int n,m;
14      int left[maxn],right[maxn];
15      bool S[maxn],T[maxn];
16      vector<int>G[maxn];
17      void init(int n, int m){
18          this->n = n;
19          this->m = m;
20          for(int i=0; i<m; i++) G[i].clear();
21      }
22      void add_edg(int u, int v){
23         G[u].push_back(v);
24      }
25      bool match(int u){
26          S[u] =true;
27          for(int i =0; i<(int )G[u].size(); i++){
28                int v = G[u][i];
29                if(T[v] == false){
30                      T[v]=true;
31                      if(left[v]==-1 || match(left[v])){
32                          left[v]=u; right[u]=v;
33                          return true;
34                      }
35                }
36          }
37          return false;
38      }
39      int solve(){
40          memset(left,-1,sizeof(left));
41          memset(right,-1,sizeof(right));
42          int ans=0;
43          for(int u =0; u<n; u++){
44               memset(S,false,sizeof(S));
45               memset(T,false,sizeof(T));
46               if(match(u)) ans++;
47          }
48          return ans;
49      }
50 }solver;
51 int main()
52 {
53      int cas;
54      scanf("%d",&cas);
55      for(int cc =1; cc<=cas; ++cc){
56          int m;
57          scanf("%d",&m);
58          for(int i=0; i<m; i++){
59              int th,tm;
60              scanf("%d:%d%d%d%d%d",&th,&tm,&P[i].sx,&P[i].sy,&P[i].tx,&P[i].ty);
61              P[i].time = th*60+tm;
62          }
63          solver.init(m,m);
64          for(int i=0; i<m; i++){
65              int a1  = abs(P[i].sx-P[i].tx)+abs(P[i].sy-P[i].ty);
66             for(int j=0; j<m; j++){
67                int a2  =  abs(P[i].tx-P[j].sx)+abs(P[i].ty-P[j].sy);
68                if( (P[i].time+a1+a2) < P[j].time ){
69                    solver.add_edg(i,j);
70                }
71            }
72          }
73          printf("%d\n",m-solver.solve());
74      }
75     return 0;
76 }
时间: 2024-10-12 21:29:17

uva1201 DAG 最小路径覆盖,转化为 二分图的相关文章

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

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

POJ 1422 DAG最小路径覆盖

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

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

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

训练指南 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),要求使用最少的出租车接

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

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

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

【最小路径覆盖】【二分图】【最大流】【Dinic】bzoj2150 部落战争

裸的最小路径覆盖. 把每个点拆点,变成二分图. 对于可以连边的点对(i,j):i->j'(1); 对于任意一点i,若i点为'.':S->i(1),i'->T(1); 答案为所有'.'的数量-最大流(最大匹配数). 引用证明: 路径覆盖中的每条简单路径除了最后一个顶点之外都有唯一的后继和它对应:因此匹配边数就是非路径结尾的结点数:因此,匹配边数达到最大时,非路径结尾的结点数大道最大,故路径结尾的节点数目最少. #include<cstdio> #include<cstri

UVA 1201 - Taxi Cab Scheme(二分图匹配+最小路径覆盖)

UVA 1201 - Taxi Cab Scheme 题目链接 题意:给定一些乘客,每个乘客需要一个出租车,有一个起始时刻,起点,终点,行走路程为曼哈顿距离,每辆出租车必须在乘客一分钟之前到达,问最少需要几辆出租车 思路:如果一辆车载完一个乘客a,能去载乘客b,就连一条有向边,这样做完整个图形成一个DAG,然后要求的最少数量就是最小路径覆盖,利用二分图最大匹配去做,把每个点拆成两点,如果有边就连边,做一次最大匹配,n - 最大匹配数就是答案 代码: #include <cstdio> #inc

[网络流专练3][最小路径覆盖问题]

题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖.提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的( 0 x , 0 y )最大流. «编程任务: