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
",m-solver.solve());
74      }
75     return 0;
76 }
原文地址:https://www.cnblogs.com/Opaser/p/4382418.html