题意:
有m个人要坐出租车,每个人给出出发时间,出发地点和目的地(以二维坐标表示),两个地点之间所花的时间计算方式是两点之间的哈密顿距离。现在需要排遣车出去,一辆车每次只能装一个人,如果一辆车在装完一个人A之后,再到达另一个人B的出发地点的时间,比这个人的出发时间至少提前1分钟,那么这个车就可以乘坐B。
问排遣的最少的车的数目。
思路:
直观的来看,每一辆车的路径是一个DAG,那么这个问题就转化成了DAG的最小路径覆盖。
最小路径覆盖的定义:在一个有向图中,找出最少的路径,使得途中的所有点都被覆盖,此题所求的最小路径覆盖是不相交的最小路径覆盖。
最小路径覆盖的算法是把每个点拆成起点i和终点i’,如果有一条边从i到j,那么就从i向j’连边,此时这个图就成为了一个二分图。
二分图的最小路径覆盖= 点数 – 二分图的最大匹配
然后此题就是两点之间连边的问题,时间可以换算成分钟数表示比较方便,然后当一个点的结束时间加上 结束点到另一个点的行驶时间,如果这个时间小于另一个点的出发时间,那么这两点之间就可以连边。
匈牙利算法,复杂度O(n^2)。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 using namespace std; 5 6 const int N = 1005; 7 typedef pair<int,int> pii; 8 9 struct node 10 { 11 int st,en; 12 13 node(int a,int b) 14 { 15 st = a; 16 en = b; 17 } 18 }; 19 20 vector<pii> ps; 21 vector<node> ns; 22 vector<int> g[N]; 23 bool vis[N]; 24 int link[N]; 25 26 int mabs(int x) 27 { 28 return x >= 0 ? x : -x; 29 } 30 31 bool dfs(int u) 32 { 33 for (int i = 0;i < g[u].size();i++) 34 { 35 int v = g[u][i]; 36 37 if (!vis[v]) 38 { 39 vis[v] = 1; 40 41 if (link[v] == -1 || dfs(link[v])) 42 { 43 link[v] = u; 44 link[u] = v; 45 46 return true; 47 } 48 } 49 } 50 51 return false; 52 } 53 54 int solve(int n) 55 { 56 memset(link,-1,sizeof(link)); 57 58 int res = 0; 59 60 for (int i = 0;i < n;i++) 61 { 62 if (link[i] == -1) 63 { 64 memset(vis,0,sizeof(vis)); 65 if (dfs(i)) res++; 66 } 67 } 68 69 return res; 70 } 71 72 int main() 73 { 74 int t; 75 76 scanf("%d",&t); 77 78 while (t--) 79 { 80 int n; 81 82 scanf("%d",&n); 83 84 ns.clear(); 85 ps.clear(); 86 87 for (int i = 0;i < n;i++) 88 { 89 g[i].clear(); 90 } 91 92 for (int i = 0;i < n;i++) 93 { 94 int a,b; 95 int x,y,z,w; 96 97 scanf("%d:%d",&a,&b); 98 scanf("%d%d%d%d",&x,&y,&z,&w); 99 100 int st = a * 60 + b; 101 int en = st + mabs(x - z) + mabs(y - w); 102 103 ns.push_back(node(st,en)); 104 ps.push_back(pii(x,y)); 105 ps.push_back(pii(z,w)); 106 } 107 108 for (int i = 0;i < n;i++) 109 { 110 for (int j = i + 1;j < n;j++) 111 { 112 pii st = ps[2*i + 1],en = ps[2*j]; 113 114 int cost = mabs(st.first - en.first) + mabs(st.second - en.second); 115 116 if (ns[i].en + cost < ns[j].st) g[i].push_back(n+j); 117 } 118 } 119 120 int ans = solve(n); 121 122 printf("%d\n",n - ans); 123 } 124 125 return 0; 126 }