HNUOJ12523 最短路径

Long Distance Taxi
Time Limit: 30000ms, Special Time Limit:75000ms, Memory Limit:65536KB
Total submit users: 11, Accepted users: 7
Problem 12523 : No special judgement
Problem description
A taxi driver, Nakamura, was so delighted because he got a passenger who wanted to go to a city thousands of kilometers away. However, he had a problem. As you may know, most taxis in Japan run on liquefied petroleum gas (LPG) because it is cheaper than gasoline. There are more than 50,000 gas stations in the country, but less than one percent of them sell LPG. Although the LPG tank of his car was full, the tank capacity is limited and his car runs 10 kilometer per liter, so he may not be able to get to the destination without filling the tank on the way. He knew all the locations of LPG stations.

Your task is to write a program that finds the best way from the current location to the destination without running out of gas.


Input
The input consists of several datasets, and each dataset is in the following format.


N M cap 
src dest 
c1, 1 c1, 2 d1 
c2, 1 c2, 2 d2 
 
cN, 1 cN, 2 dN 
s1 
s2 
 
sM


The first line of a dataset contains three integers (NMcap), where N is the number of roads (1≤N≤3000)M is the number of LPG stations (1≤M≤300), and cap is the tank capacity (1≤cap≤200) in liter. The next line contains the name of the current city (src) and the name of the destination city (dest). The destination city is always different from the current city.

The following N lines describe roads that connect cities. The road i (1≤iN) connects two different cities ci, 1 and ci, 2 with an integer distance di (0 < di≤2000) in kilometer, and he can go from either city to the other. You can assume that no two different roads connect the same pair of cities. The columns are separated by a single space. The next M lines (s1s2,..., sM) indicate the names of the cities with LPG station. You can assume that a city with LPG station has at least one road.

The name of a city has no more than 15 characters. Only English alphabet (`A' to `Z' and `a' to `z', case sensitive) is allowed for the name.

A line with three zeros terminates the input.


Output
For each dataset, output a line containing the length (in kilometer) of the shortest possible journey from the current city to the destination city. If Nakamura cannot reach the destination, output ``-1" (without quotation marks). You must not output any other characters.

The actual tank capacity is usually a little bit larger than that on the specification sheet, so you can assume that he can reach a city even when the remaining amount of the gas becomes exactly zero. In addition, you can always fill the tank at the destination so you do not have to worry about the return trip.


Sample Input
6 3 34
Tokyo Kyoto
Tokyo Niigata 335
Tokyo Shizuoka 174
Shizuoka Nagoya 176
Nagoya Kyoto 195
Toyama Niigata 215
Toyama Kyoto 296
Nagoya
Niigata
Toyama
6 3 30
Tokyo Kyoto
Tokyo Niigata 335
Tokyo Shizuoka 174
Shizuoka Nagoya 176
Nagoya Kyoto 195
Toyama Niigata 215
Toyama Kyoto 296
Nagoya
Niigata
Toyama
0 0 0
Sample Output
846
-1

题目比较有意思吧,,

一个旅程问题。有N条路,M个加油站,油箱有容量(即最远可跑多远不加油)。问从S点到T点的最短可行路径。


思路:

将S和T也当做加油站,对这些点求spfa,得到一个可行子图。对该子图做spfa即可得解。


runtime error了一天半。果断放弃...

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<map>
#define INF 0x3f3f3f3f
#define MAXN 21111
using namespace std;

struct Edge
{
 	   int v,len,next;
}E[MAXN];

int ptr[MAXN],sta[MAXN],ptr2[MAXN];
int dis[MAXN];
int N,M,D,Edgenum;
int S,T,Gnum;
void addEdge( int u,int v,int len,int *G )
{
 	 E[Edgenum].v=v;
 	 E[Edgenum].len=len;
 	 E[Edgenum].next=G[u];
 	 G[u]=Edgenum++;
}

void init()
{
 	 Edgenum=0;
 	 memset( ptr,-1,sizeof(ptr) );
 	 memset( ptr2,-1,sizeof(ptr2) );
 	 char str1[111],str2[111];
 	 map<string,int> map;
 	 scanf( "%s %s",&str1,&str2 );
 	 map[str1]=S=1;
 	 map[str2]=T=2;
 	 int rec=3,len;
 	 for( int i=0;i<N;i++ )
 	 {
	  	  scanf( "%s %s %d",&str1,&str2,&len );
	  	  if( map.find(str1)==map.end() )
	  	  	  map[str1]=rec++;
	  	  if( map.find(str2)==map.end() )
	  	  	  map[str2]=rec++;
	  	  addEdge( map[str1],map[str2],len,ptr );
	  	  addEdge( map[str2],map[str1],len,ptr );
	 }
	 Gnum=0;
	 for( int i=0;i<M;i++ )
	 {
	  	  scanf( "%s",&str1 );
	  	  sta[Gnum++]=map[str1];
  	 }
  	 sta[Gnum++]=S;
  	 sta[Gnum++]=T;
}

void spfa( int src,int *G )
{
 	 bool vis[MAXN];
 	 queue<int> queue;
 	 memset(dis,0x3f,sizeof(dis));
 	 memset(vis,0,sizeof(vis));
 	 dis[src]=0;
 	 queue.push(src);
 	 while( !queue.empty() )
 	 {
	  		int cur=queue.front();
	  		queue.pop();
	  		vis[src]=false;
	  		for( int i=G[cur];i!=-1;i=E[i].next )
	  		{
			 	 if( dis[E[i].v]>dis[cur]+E[i].len )
			 	 {
				  	 dis[E[i].v]=dis[cur]+E[i].len;
				  	 if( !vis[E[i].v] )
					 {
					  	 queue.push(E[i].v);
					  	 vis[E[i].v]=true;
		  	 		 }
			  	 }
 	 	 	}
	 }
}

int work()
{
 	int ret;
 	for( int i=0;i<Gnum;i++ )
	{
	 	spfa( sta[i],ptr );
	 	for( int j=0;j<Gnum;j++ )
	 	{
		 	 if( dis[sta[j]]<=D )
		 	 {
			  	 addEdge( sta[i],sta[j],dis[sta[j]],ptr2 );
			  	 addEdge( sta[j],sta[i],dis[sta[j]],ptr2 );
			 }
 	 	}
	}
	spfa(S,ptr2);
	return dis[T];
}

int main()
{
 	//freopen("test.in","r",stdin );
 	//freopen("test.out","w",stdout );
 	while( scanf("%d %d %d",&N,&M,&D)!=EOF )
 	{
	 	   D*=10;
	 	   if( !N&&!M&&!D )
	 	   	   break;
	 	   init();
	 	   int ans=work();
	 	   if( ans==INF )
	 	   	   ans=-1;
	 	   printf( "%d\n",ans );
  	}
 	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值