现在的位置: 首页 > 综合 > 正文

SWUN 1454 – Hotel booking

2012年09月17日 ⁄ 综合 ⁄ 共 3327字 ⁄ 字号 评论关闭

 

Hotel booking

时间限制(普通/Java) : 4000 MS/ 10000 MS          运行内存限制 : 65536 KByte
总提交 : 1            测试通过 : 1

描述

    A transport company often needs to deliver goods from one city to another city. The transport company has made a special deal with a hotel chain which allows its drivers to stay in the hotels of this chain for free.
Drivers are only allowed to drive up to 10 hours a day. The transport company wants to find a route from the starting city to the destination city such that a driver can always spend the night in one of the hotels of the hotel chain, and that he needs to drive
at most 10 hours from one hotel to the next hotel (or the destination). Of course, the number of days needed to deliver the goods should also be minimized.

输入

    The input file contains several test cases. Each test case starts with a line containing an integer n,
(2 ≤ n ≤ 10000
), the number of cities to be considered when planning the route. For simplicity, cities are numbered from 1 to n,
where 1 is the starting city, and
 n is the destination city. The next line contains an integer h followed
by the numbers
 c1, c2, ..., ch indicating the numbers of the cities where
hotels of the hotel chain are located. You may assume that
 0 ≤ h ≤ min(n, 100). The third line of each test case contains an integer m (1
≤ m ≤ 105
), the number of roads to be considered for planning the route. The following m lines
describe the roads. Each road is described by a line containing 3 integers
 a, b, t (1 ≤ a, b ≤ n and 1
≤ t ≤ 600
), where a, b are the two cities connected by the road,
and
 t is the time in minutes needed by the driver to drive from one end of the road to the other. Input is
terminated by
 n = 0.

输出

    For each test case, print one line containing the minimum number of hotels the transport company has to book for a delivery from city 1 to city n.
If it is impossible to find a route such that the driver has to drive at most 10 hours per day, print
 -1 instead.

样例输入

6
3 2 5 3
8
1 2 400
3 2 80
3 4 301
4 5 290
5 6 139
1 3 375
2 5 462
4 6 300
3
0
2
1 2 371
2 3 230
0

样例输出

2
-1

提示

 

题目来源

University of Ulm

 

题目地址:

http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1454

 

二维spfa,优先队列优化。 (其实我就是当作BFS来做,只不过做法类似spfa)

 

 

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;

struct Edge{
	int nx,cost,v;
}edge[210000];
int ef[10010],tol=0;

void add_edge(int a,int b,int cost){
	edge[tol].v=b;
	edge[tol].cost=cost;
	edge[tol].nx=ef[a];
	ef[a]=tol++;
}

struct Node{
	int u,minute,vis;
	Node(){};
	Node(int uu,int mm,int vv){
		u=uu; // 当前所在位置
		minute=mm; // 记录从旅馆/起点出发,到达u位置所花费的最时间
		vis=vv; // 记录入住次数
	}
	bool friend operator<(Node a,Node b){ // 优先级为: 访问旅馆次数较少的点先走,次数相同则以花费时间少的点先走
		return a.vis!=b.vis?a.vis>b.vis:a.minute>b.minute;
	}
};

priority_queue<Node>que;

int n;

int has[10010];
int Time[10010]; // Time[v]记录【v位置】与 【起点/最近的旅馆】 的最短距离
int Count[10010]; // Count记录当前已入住的次数
int spfa(){
	int k,v,tmp;
	Node now,nx;
	que.push(Node(1,0,0));
	while(!que.empty()){
		now=que.top();
		que.pop();
		if(now.u==n) return now.vis;
		for(k=ef[now.u];k!=-1;k=edge[k].nx){
			v=edge[k].v;
	 		if(Count[v]<now.vis){ // 当访问旅馆次数增加,那么之前记录的时间作废 
	 			Count[v]=now.vis;
		 		Time[v]=601; // 重新记录时间为601分钟 
		 	}
	 		tmp=now.minute+edge[k].cost; // 从【起点/旅馆】出发,到达v时所花费的时间 
	 		if(tmp>=Time[v] || has[v]==-1) continue; // 时间比记录的Time[v]还高,那么不再访问 
	 		Time[v]=tmp;
	 		que.push(Node(v,tmp,now.vis));
			if(has[v]==1){ // 一开始写在continue那句之前,样例都没过,囧 
	 			has[v]=-1; // 标记住过的旅馆不再住,(为何?既然之前更优的走法先入住了,现在更搓的走法何必再入住。可以仔细想哈)
	 			que.push(Node(v,0,now.vis+1));
	 		}
		}
	}
	return -1;
}

void INIT(){
	int i;
	for(i=1;i<=n;i++){
		has[i]=0;
		ef[i]=Count[i]=-1;
	}
	tol=0;
	while(!que.empty()) que.pop();
}

int main(){
	int m,a,b,len;
	while(~scanf("%d",&n)){
		if(!n) break;
		INIT();
		scanf("%d",&m);
		while(m--){
			scanf("%d",&a);
			has[a]=1;
		}
		scanf("%d",&m);
		while(m--){
			scanf("%d%d%d",&a,&b,&len);
			add_edge(a,b,len);
			add_edge(b,a,len);
		}
		printf("%d\n",spfa());
	}	
	return 0;
}

 

抱歉!评论已关闭.