Taxi Cab Scheme HDU - 1350 二分图最小路径覆盖

题目链接: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();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35320178/article/details/81568705