POJ2060 Taxi Cab Scheme【二分圖最小路徑覆蓋】
阿新 • • 發佈:2019-02-08
題目連結:
題目大意:
計程車公司每天有有N項預約,每項預約有開始時間(xx:xx),出發地點(a,b)與目的地點(c,d)。
完成這項預約行駛需要的時間是|a-c| + |b-d|分鐘。一輛車可以在完成一個預約i後再去完成另一
個預約j。條件就是需要再預約j開始時間的前1分鐘達到出發地點。問:最少需要多少輛車能完成
所有的預約。
思路:
二分圖最小路徑覆蓋問題。根據題意,我們可以建立一個二分圖,兩邊分別為N項預約。對於兩個
預約i和j,如果能在完成預約i後有時間趕去完成預約j,就建立一條i指向j的邊。因為開始時間有先
後,那麼這個圖是有向無環圖。如果一輛車可以順著一條路徑由i經過若干條邊和若干個點到點j,
則該路徑上所有的預約就只需要用一輛車就可以完成預約。那麼問題就變為了:求該二分圖最小路
徑覆蓋問題。而二分圖最小路徑 = 總點數 - 二分圖最大匹配,用匈牙利演算法求出二分圖最大匹配就
可以得到結果了。
AC程式碼:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int MAXN = 550; struct Node { int time; int a,b,c,d; }Dot[MAXN]; int Dist(Node x,Node y) { return abs(x.a-y.c) + abs(x.b-y.d); } bool Map[MAXN][MAXN],Mask[MAXN]; int NX,NY; int cx[MAXN],cy[MAXN]; int FindPath(int u) { for(int i = 1; i <= NY; ++i) { if(Map[u][i] && !Mask[i]) { Mask[i] = 1; if(cy[i] == -1 || FindPath(cy[i])) { cy[i] = u; cx[u] = i; return 1; } } } return 0; } int MaxMatch() { for(int i = 1; i <= NX; ++i) cx[i] = -1; for(int i = 1; i <= NY; ++i) cy[i] = -1; int res = 0; for(int i = 1; i <= NX; ++i) { if(cx[i] == -1) { for(int j = 1; j <= NY; ++j) Mask[j] = 0; res += FindPath(i); } } return res; } int main() { int T,N,h,s; scanf("%d",&T); while(T--) { scanf("%d",&N); for(int i = 1; i <= N; ++i) { scanf("%d:%d %d %d %d %d",&h,&s,&Dot[i].a,&Dot[i].b,&Dot[i].c,&Dot[i].d); Dot[i].time = h*60+s; } memset(Map,0,sizeof(Map)); for(int i = 1; i <= N; ++i) { for(int j = i+1; j <= N; ++j) { if(Dot[i].time + Dist(Dot[i],Dot[i]) + Dist(Dot[j],Dot[i]) < Dot[j].time) Map[i][j] = 1; } } NX = NY = N; printf("%d\n",N-MaxMatch()); } return 0; }