題目連接:https://vjudge.net/problem/UVALive-3126ios
題解:算法
最小路徑覆蓋:即在圖中找出儘可能少的路徑,使得每一個結點剛好只存在於一條路徑上。其中單獨一個點也能夠是一條路徑。ide
1.若是接完x以後能繼續接y,那麼x、y之間連一條有向邊:x-->y。spa
2.利用匈牙利算法,求出最大匹配數m。假設總共有n個客人,那麼結果就是:n-m。即:.net
最小路徑覆蓋 = 整體 - 最大匹配數 。 爲什麼?code
答:每存在一個配對,就意味着有一個乘客能夠坐別人打過的車,而不須要再另設一輛車去接他。因此,有幾個配對,就能免去幾輛車,因此實際須要的車就是n-m。又由於是「最大」匹配數, 即m最大, 因此n-m最小。因此所需的車也最少。抽象化,因此:最小路徑覆蓋 = 整體 - 最大匹配數。blog
代碼以下:get
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 }