LA 3126 - Taxi Cab Scheme DAG上的二分匹配

来源:互联网 发布:苹果52g网络 编辑:程序博客网 时间:2024/05/23 12:57

题目链接:LA 3126 - Taxi Cab Scheme

题目大意: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 <stdio.h>  #include <string.h>  #include <algorithm>#define abs(X) ((X) > 0 ? (X) : -(X))#define REP(I, X) for(int I = 0; I < X; ++I)#define clear(A, X, SIZE) memset(A, X, sizeof(A[0]) * (SIZE + 1))  using namespace std;  const int maxN = 2000;  const int maxE = 1000000;  struct Edge{          int v, n;  }edge[maxE];  struct Node{        int s, e, x1, y1, x2, y2;}a[maxN];int adj[maxN], cntE, vis[maxN], link[maxN];  int n;void addedge(int u, int v){          edge[cntE].v = v; edge[cntE].n = adj[u]; adj[u] = cntE++;  }  int find(int u){          for(int i = adj[u]; ~i; i = edge[i].n) if(!vis[edge[i].v]){                  int v = edge[i].v;                  vis[v] = 1;                  if(link[v] == -1 || find(link[v])){                          link[v] = u;                          return 1;                }          }          return 0;  }  int match(){          int ans = 0;          clear(link, -1, n);          REP(i, n){                  clear(vis, 0, n);                  ans += find(i);          }          return ans;  }  void work(){          int h, m;          scanf("%d", &n);        clear(adj, -1, n);          cntE = 0;          REP(i, n){                  scanf("%d:%d%d%d%d%d", &h, &m, &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2);                a[i].s = h * 60 + m;                a[i].e = a[i].s + abs(a[i].x1 - a[i].x2) + abs(a[i].y1 - a[i].y2);        }        REP(i, n) REP(j, n){                if(a[i].e + abs(a[i].x2 - a[j].x1) + abs(a[i].y2 - a[j].y1) < a[j].s) addedge(i, j);        }        printf("%d\n", n - match());  }  int main(){         int t;         for(scanf("%d", &t); t; --t) work();        return 0;  }  



0 0