UVALive3126 Taxi Cab Scheme —— 最小路径覆盖
题目链接:https://vjudge.net/problem/UVALive-3126
题解:
最小路径覆盖:即在图中找出尽量少的路径,使得每个结点恰好只存在于一条路径上。其中单独一个点也可以是一条路径。
1.如果接完x之后能继续接y,那么x、y之间连一条有向边:x-->y。
2.利用匈牙利算法,求出最大匹配数m。假设总共有n个客人,那么结果就是:n-m。即:
最小路径覆盖 = 总体 - 最大匹配数 。 为何?
答:每存在一个配对,就意味着有一个乘客可以坐别人打过的车,而不需要再另设一辆车去接他。所以,有几个配对,就能免去几辆车,所以实际需要的车就是n-m。又因为是“最大”匹配数, 即m最大, 所以n-m最小。所以所需的车也最少。抽象化,所以:最小路径覆盖 = 总体 - 最大匹配数。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 const int INF = 2e9; 14 const int MOD = 1e9+7; 15 const int MAXN = 1e3+10; 16 17 int n; 18 int M[MAXN][MAXN], link[MAXN]; 19 bool vis[MAXN]; 20 21 struct Node 22 { 23 int time[2], sor[2], des[2]; 24 }a[MAXN]; 25 26 bool dfs(int u) 27 { 28 for(int i = 1; i<=n; i++) 29 if(M[u][i] && !vis[i]) 30 { 31 vis[i] = true; 32 if(link[i]==-1 || dfs(link[i])) 33 { 34 link[i] = u; 35 return true; 36 } 37 } 38 return false; 39 } 40 41 int hungary() 42 { 43 int ret = 0; 44 memset(link, -1, sizeof(link)); 45 for(int i = 1; i<=n; i++) 46 { 47 memset(vis, 0, sizeof(vis)); 48 if(dfs(i)) ret++; 49 } 50 return ret; 51 } 52 53 bool judge(Node x, Node y) 54 { 55 int t1 = x.time[0]*60+x.time[1]; 56 int t2 = y.time[0]*60+y.time[1]; 57 int dis1 = abs(x.des[0]-x.sor[0]) + abs(x.des[1]-x.sor[1]); 58 int dis2 = abs(y.sor[0]-x.des[0]) + abs(y.sor[1]-x.des[1]); 59 return (t1+dis1+dis2+1<=t2); 60 } 61 62 int main() 63 { 64 int T; 65 scanf("%d", &T); 66 while(T--) 67 { 68 scanf("%d", &n); 69 for(int i = 1; i<=n; i++) 70 { 71 scanf("%d:%d", &a[i].time[0], &a[i].time[1]); 72 scanf("%d%d%d%d", &a[i].sor[0], &a[i].sor[1], &a[i].des[0], &a[i].des[1]); 73 } 74 75 memset(M, 0, sizeof(M)); 76 for(int i = 1; i<=n; i++) 77 for(int j = 1; j<=n; j++) 78 if(i!=j && judge(a[i], a[j])) 79 M[i][j] = 1; 80 81 int cnt = hungary(); 82 printf("%d\n", n-cnt); 83 } 84 }