题目链接:HDU-1350
这道题和HDU-1151Air Riad十分相似,只是这道题没有给出边,需要自行造边。同样的将有向图转化为二分图,每条左边的点X连向右边的点Y的边的意义为可以先接乘客X,再接乘客Y(即送完乘客X后直接开到乘客Y的上车地点小于乘客Y的上车时间(注意是小于,没有等于))这种方案在时间上可行。即初始需要M个司机,每个匹配都可以省掉一个司机,故本题就是求M-最大匹配,即最小路径覆盖。
AC代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#define M 505
using namespace std;
int count(int a,int b,int c,int d){//计算两点之间的距离
return abs(c-a)+abs(d-b);
}
struct node{
int st,ed,x1,y1,x2,y2;//st为起始时间(也就是接到乘客的时间),ed为结束时间(也就是送完乘客的时间)
int Init(int time,int a,int b,int c,int d){
st=time;
x1=a;
y1=b;
x2=c;
y2=d;
ed=count(x1,y1,x2,y2)+st;
}
}A[M];
int C(int x,int y){
return count(A[x].x2,A[x].y2,A[y].x1,A[y].y1);
}
int chose[M];
bool used[M];
vector<int>way[M];
bool find(int now){//匈牙利算法求最大匹配
for(int i=0;i<way[now].size();i++){
int nxt=way[now][i];
if(!used[nxt]){
used[nxt]=1;
if(!chose[nxt]||find(chose[nxt])){
chose[nxt]=now;
return 1;
}
}
}
return 0;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(chose,0,sizeof(chose));
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++){
int t1,t2,x1,y1,x2,y2;
scanf("%d:%d %d %d %d %d",&t1,&t2,&x1,&y1,&x2,&y2);
A[i].Init(t1*60+t2,x1,y1,x2,y2);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
if(i==j)continue;
if(A[i].ed+C(i,j)<A[j].st)way[i].push_back(j);//若可以接完乘客i在去接乘客j来的及
}
}
int ans=0;
for(int i=1;i<=m;i++){
memset(used,0,sizeof(used));
ans+=find(i);
}
printf("%d\n",m-ans);//求最小路径覆盖
for(int i=1;i<=m;i++)way[i].clear();
}
}