您的位置:首页 > 其它

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

2016-03-11 17:36 281 查看
http://poj.org/problem?id=2060

题意:有n个任务:开始时间、起始地点、终止地点。每个地点可以派出一辆出租车,如果出租车完成任务i后还可以到达任务j,那么它可以继续执行任务j。现在问最少可以排除多少辆出租车?

乍一看,像是最小路径的问题,关键有个地方是,即使任务A的终点和任务B的起点相同,也不代表路径A-B合法,还要判断:任务i的开始时间+任务i的完成时间+从任务i的目的地到达任务j的起始地点所花费的时间<任务j的开始时间

因此建图的话,得以任务为点,如果任务B能接着任务B继续作,就在他们之间连一条边。显然,这样建图的话,每一条路径只需要一辆车就能走完,因此题目求最少车辆完成任务,转化成了  最后求最少路径数,覆盖所有任务点。

此二分图的两部分点集,都是n个任务,因为任务是按时间递增排序的,所以与任务【i】连边只需要j>i部分的任务【j】即可

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;

//顶点编号从0开始的
const int MAXN = 510;
int uN,vN;//u,v的数目,使用前面必须赋值
int g[MAXN][MAXN];//邻接矩阵
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
for(int v = 0; v < vN;v++)
if(g[u][v] && !used[v])
{
used[v] = true;
if(linker[v] == -1 || dfs(linker[v]))
{
linker[v] = u;
return true;
}
}
return false;
}
int hungary()
{
int res = 0;
memset(linker,-1,sizeof(linker));
for(int u = 0;u < uN;u++)
{
memset(used,false,sizeof(used));
if(dfs(u))res++;
}
return res;
}
int t1[505],t2[505];
int a[505],b[505],c[505],d[505];
int dis(int i,int j)
{
int tt1=t1[i]*60+t2[i];
int tt2=t1[j]*60+t2[j];
return tt2-tt1;
}
int main()
{
int i,j;
int t;cin>>t;
while(t--)
{
memset(g,0,sizeof(g));
int n;
cin>>n;
for (i=0;i<n;i++)
scanf("%d:%d %d %d %d %d",&t1[i],&t2[i],&a[i],&b[i],&c[i],&d[i]);

for (i=0;i<n;i++)
{
for (j=i+1;j<n;j++)
{
int need=abs(c[i]-a[j])+abs(d[i]-b[j])+1+abs(c[i]-a[i])+abs(b[i]-d[i]);
int has=dis(i,j);
if (has>=need)
g[i][j]=1;
}
}
uN=vN=n;
int ret=hungary();
//最小路径覆盖=最大独立集=n-最大匹配数
printf("%d\n",n-ret );
}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: