题目大意就是,有一个图,上面有一些顶点,代表一些城市,在某些时刻, 某个城市里会有人需要礼物, 哈利波特需要及时的将礼物送到,但是哈利每1秒只能走一个单位长度,所以他需要朋友的帮助,来使所有的人都能及时的收到礼物。问需要的最少的朋友个数。
那么看完题目后,实际上可以发现其跟路径覆盖非常有关系,因为是一些人走一些路径来将礼物送到。
所以要先将任意两点间的最短路求好。然后枚举任意两个任务,如果两点间的距离小于两点间的时间差,当然,这个时间差是有先后顺序的,这两个任务就可以进行连边,就这样,到最后可以发现是经典的最小路径覆盖模型。
要求最少需要多少个朋友帮他送礼物,每个城市在一个时间有人需要礼物,如果两个城市之间的距离小于两个城市中两个需要礼物的时间差的话,这两个礼物一个人送就可以了。就是用最少的人到达所有需要礼物的点,就是二分图的最小路径覆盖问题,之前我们要求出任意两点之间的最短距离,floyd求最短路。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define inf 99999999
int map[1010][1010];//只是求最短距离,不在find中
int link[1010],mark[1010];
int ma[1010][1010];//主要变量在find中
int m,n;
struct point
{
int x;
int t;
}p[1000];
int cmp(const void *a,const void *b)//快排,是为了让一个人给你更多送礼物。。
{
struct point *c=(struct point*)a;
struct point *d=(struct point*)b;
if(c->t!=d->t)
return c->t-d->t;
return c->x-d->x;
}
int find(int k)
{
int i;
for(i=0;i<n;i++)
{
if(mark[i]==-1&&ma[k][i])、、当m从零开始时,link和mark都要初始化为-1,(不然易岀错),当m从一开始时初始化为-1 和0均可以。。
{
mark[i]=1;
if(link[i]==-1||find(link[i]))
{
link[i]=k;
return 1;
}
}
}
return 0;
}
void flory()//最短距离的算法。。
{
int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
for(k=0;k<n;k++)
{
if(map[j][i]+map[i][k]<map[j][k])
map[j][k]=map[j][i]+map[i][k];
}
}
int main()
{
int i,j,k,Q,a,b,c,sum,r=0;
scanf("%d",&k);
while(k--)
{
r++;
memset(ma,0,sizeof(ma));
memset(link,-1,sizeof(link));
scanf("%d%d%d",&n,&m,&Q);
for(i=0;i<n;i++)//先初始化无穷大。。再利用flory
{
for(j=0;j<n;j++)
map[i][j]=inf;
map[i][i]=0;
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(map[a][b]>c)//两点之间了距离一样,双向。
{
map[a][b]=c;
map[b][a]=c;
}
}
flory();
for(i=0;i<Q;i++)
scanf("%d%d",&p[i].x,&p[i].t);
qsort(p,Q,sizeof(p[0]),cmp);
for(i=0;i<Q;i++)
for(j=i+1;j<Q;j++)
{
if(map[p[i].x][p[j].x]<=p[j].t-p[i].t)//满足条件ma置为一;
ma[i][j]=1;
}
sum=0;
for(i=0;i<Q;i++)
{
memset(mark,-1,sizeof(mark));
if(find(i))
sum++;
}
printf("Case %d: %d\n",r,Q-sum-1);
}
return 0;
}