poj 3216 (最小路径覆蓋)

题意:有n个地方,m个任务,每个任务给出地点,开始的时间和完成需要的时间,问最少派多少工人去可以完成所有的任务。给出任意两点直接到达需要的时间,-1代表不能到达。

思路:很明显的最小路径覆蓋问题,刚开始脑子抽了,没求最短路直接就做了,题目只给了两点间直接到达的时间,还可以间接到达,用floyd求出最短路。。。






#include<stdio.h>
#include<string.h>
const int N=300;
const int inf=0x3fffffff;
int head[N],num,match[N],link[N],map[30][30],n,m;
struct edge
{
	int st,ed,next;
}e[N*N];
struct node
{
	int id,stime,etime;
}P[N];
void addedge(int x,int y)
{
	e[num].st=x;e[num].ed=y;e[num].next=head[x];head[x]=num++;
}
int find(int u)//二分匹配
{
	int i,v;
	for(i=head[u];i!=-1;i=e[i].next)
	{
		v=e[i].ed;
		if(link[v]==0)
		{
			link[v]=1;
			if(match[v]==-1||find(match[v])==1)
			{
				match[v]=u;
				return 1;
			}
		}
	}
return 0;
}
void Floyd()//最短路
{
	int i,j,k;
	for(k=1;k<=n;k++)
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				if(map[i][j]>map[i][k]+map[k][j])
					map[i][j]=map[i][k]+map[k][j];
}
int main()
{
	int i,j;
	while(scanf("%d%d",&n,&m),n+m)
	{
		memset(map,-1,sizeof(map));
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
			{
				scanf("%d",&map[i][j]);
				if(map[i][j]==-1)
					map[i][j]=inf;
			}
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&P[i].id,&P[i].stime,&P[i].etime);
				P[i].etime+=P[i].stime;
		}
		Floyd();
		memset(head,-1,sizeof(head));
		num=0;
		for(i=1;i<=m;i++)
		{
			for(j=1;j<=m;j++)
			{
				if(i==j||map[i][j]>=inf)
					continue;
				if(P[i].etime+map[P[i].id][P[j].id]<=P[j].stime)//完成i任务后可以赶到j
					addedge(i,j);
			}
		}
		memset(match,-1,sizeof(match));
		int sum=0;
		for(i=1;i<=m;i++)
		{
			memset(link,0,sizeof(link));
			sum+=find(i);
		}
		printf("%d\n",m-sum);
	}
	return 0;
}

点赞