Travelling Fee ZOJ - 2027

Samball is going to travel in the coming vacation. Now it's time to make a plan. After choosing the destination city, the next step is to determine the travel route. As this poor guy has just experienced a tragic lost of money, he really has limited amount of money to spend. He wants to find the most costless route. Samball has just learned that the travel company will carry out a discount strategy during the vacation: the most expensive flight connecting two cities along the route will be free. This is really a big news.

Now given the source and destination cities, and the costs of all the flights, you are to calculate the minimum cost. It is assumed that the flights Samball selects will not have any cycles and the destination is reachable from the source.


Input

The input contains several test cases, each begins with a line containing names of the source city and the destination city. The next line contains an integer m (<=100), the number of flights, and then m lines follow, each contains names of the source city and the destination city of the flight and the corresponding cost. City names are composed of not more than 10 uppercase letters. Costs are integers between 0 to 10000 inclusively.

Process to the end of file.


Output

For each test case, output the minimum cost in a single line.


Sample Input

HANGZHOU BEIJING
2
HANGZHOU SHANGHAI 100
SHANGHAI BEIJING 200


Sample Output

100

题意概括:给出起始城市和终点城市,然后给出n条航班的信息,包括起点、终点和价格,现在让你选择合适的航班从起点到达终点,在你选择的航班里面有一条的花费是可以报销的,具体报销那条航线由你选择。


解题思路:如果不报销花费,那么就是一道最短路径的模板题,但是现在需要报销一条,报销一条也就是说由一条航线的花费是0,如果仍按最短路径算然后减去路径中的最大花费明显是不行的。这道题的数据量比较小,可以先把每条航线的花费依次赋值为0(相当于把每条航线都当成报销的航线依次进行遍历),计算最小花费。最后在这些最小花费中找出真正地最小花费。


代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f
struct city
{
	int s,e;
	int w;
}fl[300];
char start[20],end[20];
int n,a,z,f[600],book[600],d[600];
int map[300][300];
void Dijkstra(int a,int z,int k)
{
	int i,j;
	memset(book,0,sizeof(book));
	memset(d,0,sizeof(d));
//	printf("%d\n",k);
	for(i=1;i<=k;i++)
	{
		d[i]=map[a][i];
	//	printf("%d\n",d[i]);
	}
//	printf("\n");
	d[a]=0;
	for(i=1;i<=k;i++)
	{
		int min_cost=INF;
		int index=-1;
		for(j=1;j<=k;j++)
		{
			if(book[j]==0&&d[j]<min_cost)
			{
				index=j;
				min_cost=d[j];
			}
		}
		if(index==-1)
			break;
		book[index]=1;
	//	printf("%d  ---  %d\n",index,min_cost);
		for(j=1;j<=k;j++)
		{
			if(book[j]==0&&d[j]>min_cost+map[index][j])
			{
				d[j]=min_cost+map[index][j];
			}
		}
	}
}
int main()
{
	int i,j,k;
	char st[300][20],en[300][20];
	while(scanf("%s%s",start,end)!=EOF)
	{
		memset(st,0,sizeof(st));
		memset(en,0,sizeof(en)); 
		scanf("%d",&n);
		for(i=0;i<n;i++)
		{
			scanf("%s%s%d",st[i],en[i],&fl[i].w);
		}
		if(strcmp(start,end)==0)
		{
			printf("0\n");
		}
		else
		{
		
		fl[0].s=1;fl[0].e=2;
		k=3;
		for(i=1;i<n;i++)//给每个城市从1可以往后编号 
		{
			for(j=0;j<i;j++)
			{
				int flag=0;
				if(strcmp(st[i],st[j])==0)
				{
					fl[i].s=fl[j].s;
					flag=1;
					//printf("%s %s\n",st[i],st[j]);
				}	
				if(strcmp(st[i],en[j])==0)
				{
					fl[i].s=fl[j].e;
					flag=1;
					//printf("%s %s\n",st[i],en[j]);
				}
				if(flag==1)
					break;
			}
			if(j==i)
			{
				//printf("k==%d\n",k);
				fl[i].s=k;
				k++;	
			}
			for(j=0;j<i;j++)
			{
				int flag=0;	
				if(strcmp(en[i],en[j])==0)
				{
					//printf("%s %s\n",en[i],en[j]);
					fl[i].e=fl[j].e;
					flag=1;
				}
				if(strcmp(en[i],st[j])==0)
				{
					//printf("%s %s\n",en[i],st[j]);
					fl[i].e=fl[j].s;
					flag=1;
				}
				if(flag==1)
					break;
				
			}
			if(j==i)
			{
				//printf("k==%d\n",k);
				fl[i].e=k;
				k++;
			}
		}
		
		memset(map,INF,sizeof(map));
		for(i=0;i<n;i++)//找到起点城市和终点城市的编号 
		{
			if(strcmp(start,st[i])==0)
			{
				a=fl[i].s;
			}
			if(strcmp(start,en[i])==0)
			{
				a=fl[i].e;
			}
			if(strcmp(end,st[i])==0)
			{
				z=fl[i].s;
			}
			if(strcmp(end,en[i])==0)
			{
				z=fl[i].e;
			}
			if(map[fl[i].s][fl[i].e]>fl[i].w)//把每条路的权值存入map里面 
			{
				map[fl[i].s][fl[i].e]=map[fl[i].e][fl[i].s]=fl[i].w;
			}
			//printf("%d %d %d\n",fl[i].s,fl[i].e,fl[i].w);
		}
			//printf("%d %d\n",a,z);
			int min=99999999;
			for(i=0;i<n;i++) //可以选择一个航线报销,肯定选择最贵的,所以把每个航线 
			{		 //遍历为0(相当于这条线报销的情况下),找出最小的花费 
				int t1=map[fl[i].s][fl[i].e];
				map[fl[i].s][fl[i].e]=map[fl[i].e][fl[i].s]=0;
				Dijkstra(a,z,k-1);
				if(d[z]<min)
					min=d[z];
				map[fl[i].s][fl[i].e]=map[fl[i].e][fl[i].s]=t1;
			}
			printf("%d\n",min);
		}
		memset(start,0,sizeof(start));
		memset(end,0,sizeof(end)); 
	}
	return 0;	
} 

猜你喜欢

转载自blog.csdn.net/gakki_wpt/article/details/79475189
ZOJ