POJ--2060[Taxi Cab Scheme] 最小路径覆盖

45 篇文章 0 订阅
 

题目大意:

给你M个出租车请求,告诉你每个请求的出发时间s,起点坐标(x1,y1),终点坐标(x2,y2)。要你求出完成所有请求所需要的最少出租车辆数。(其中若一辆出租车完成请求u后,从u的终点赶到请求v的起点后的时间小于请求v的起始时间。那么这辆出租车还可以去完成请求v)。

 

思路分析:

将一个请求作为有向无环图的一个节点,若请求u完成后能够赶到请求v,那么在有向图u到v之间连有向边。然后求这个有向图的最小路径覆盖。注意是有向的!!!

最小路径覆盖数=节点数M-最大匹配数

 

感想:

分别用邻接矩阵和邻接表实现。发现我用邻接表写的比邻接矩阵还慢!!!。。。。受挫。。。。。。

 

CODE(1):邻接矩阵

/*最小路径覆盖*/
/*有向无环图*/
/*最小路径覆盖 =  |M| - 最大匹配数*/

/*邻接矩阵实现*/
/*AC代码:125ms*/
#include <iostream>
#include <cmath>
#include <string>
#define MAXN 505
using namespace std;
bool map[MAXN][MAXN];
bool flag[MAXN];
int result[MAXN];
struct px
{
	int x1,y1,x2,y2,s,e;
};
struct px P[MAXN];
int M;
int Find(int a)
{
	int i;
	for(i=1;i<=M;i++)
	{
		if(map[a][i]&&!flag[i])
		{
			flag[i]=true;
			if(result[i]==0||Find(result[i]))
			{
				result[i]=a;
				return 1;
			}
		}
	}
	return 0;
}
int MaxMatch()
{
	int ans=0,i;
	memset(result,0,sizeof(result));//忘记初始WA好几次!!!
	for(i=1;i<=M;i++)
	{
		memset(flag,false,sizeof(flag));
		ans+=Find(i);
	}
	return ans;
}
void Build()
{
	memset(map,false,sizeof(map));
	int i,j,k;
	for(i=1;i<=M;i++)
	{
		for(j=M;j>i;j--)
		{
			if((P[i].e+abs(P[j].x1-P[i].x2)+abs(P[j].y1-P[i].y2))<P[j].s)
				map[i][j]=true;
			if(P[i].e>=P[j].s)
				break;
		}
	}
}
int main()
{
	int T,i,j,h,m;
	//char ss[10];
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&M);
		for(i=1;i<=M;i++)
		{
			//scanf("%s",ss);
            //sscanf(ss,"%d%*[:]%d",&h,&m);
			scanf("%d:%d",&h,&m);
			scanf("%d%d%d%d",&P[i].x1,&P[i].y1,&P[i].x2,&P[i].y2);
			P[i].s=h*60+m;
			P[i].e=P[i].s+abs(P[i].x1-P[i].x2)+abs(P[i].y1-P[i].y2);
		}
		Build();
		printf("%d\n",M-MaxMatch());
	}
	return 0;
}


 

CODE(2):邻接表实现

/*最小路径覆盖*/
/*有向无环图*/
/*最小路径覆盖 =  |M| - 最大匹配数*/
/*用邻接表*/
/*AC代码:235ms*/
#include <iostream>
#include <cmath>
#include <string>
#define MAXN 505
using namespace std;
bool flag[MAXN];
int result[MAXN];
int link[MAXN][MAXN];
struct px
{
	int x1,y1,x2,y2,s,e;
};
struct px P[MAXN];
int M;
int Find(int pos)
{
	int i;
	for(i=1;i<=link[pos][0];i++)
	{
		int t=link[pos][i];
		if(!flag[t])//注意
		{
			flag[t]=true;
			if(result[t]==0||Find(result[t]))
			{
				result[t]=pos;
				return 1;
			}
		}
	}
	return 0;
}
int MaxMatch()
{
	int ans=0,i;
	memset(result,0,sizeof(result));//忘记初始WA好几次!!!
	for(i=1;i<=M;i++)
	{
		if(link[i][0])
		{
			memset(flag,false,sizeof(flag));
			ans+=Find(i);
		}
	}
	return ans;
}
void Build()
{
	int i,j,k;
	memset(link,0,sizeof(link));
	for(i=1;i<=M;i++)
	{
		for(k=0,j=M;j>i;j--)
		{
			if((P[i].e+abs(P[j].x1-P[i].x2)+abs(P[j].y1-P[i].y2))<P[j].s)
				link[i][++k]=j;
			if(P[i].e>=P[j].s)
				break;
		}
		link[i][0]=k;
	}
}
int main()
{
	int T,i,j,h,m;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&M);
		for(i=1;i<=M;i++)
		{
			scanf("%d:%d",&h,&m);
			scanf("%d%d%d%d",&P[i].x1,&P[i].y1,&P[i].x2,&P[i].y2);
			P[i].s=h*60+m;
			P[i].e=P[i].s+abs(P[i].x1-P[i].x2)+abs(P[i].y1-P[i].y2);
		}
		Build();
		printf("%d\n",M-MaxMatch());
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__简言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值