UVA - 11280 Flying to Fredericton(二维SPFA)

181 篇文章 0 订阅
99 篇文章 0 订阅


Link:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25133



Description

Download as PDF

Problem C

FLYING TO FREDERICTON

After being inspired by Salvador Dali's artwork, Brett decided he would like to travel to Fredericton, New Brunswick to visit the Beaverbrook Art Gallery.

Brett lives in Calgary, and would like to find the cheapest flight or flights that would take him to Fredericton. He knows that a direct flight from Calgary to Fredericton, if one exists, would be absurdly expensive, so he is willing to tolerate a certain number of stopovers. However, there are multiple airlines in Canada with so many different flights between different cities now, which makes it very difficult for Brett to find the least expensive way to Fredericton! Can you write a program to help Brett plan his route?

Map showing a sample of the flights that would take Brett to Fredericton.

You will be given a list of cities between and including Calgary and Fredericton. The cities will be given in order of "nearest" to "farthest". The first city will always be "Calgary" and the last "Fredericton".

You will also be given a list of flights between pairs of cities, and the associated cost for each flight, taxes included. There will never be a flight from a farther city to a nearer city - Brett has already discarded those flights, deeming them to be a waste of time and money. Bear in mind, however, that there may be more than one flight between any two cities, as Brett is considering flights from all airlines.

Finally, you are presented with a number of queries. Each query is a single integer indicating the maximum number of stopovers Brett will tolerate. For each query, your program must calculate the least total cost of flights that would take Brett from Calgary to Fredericton with no more than the requested number of stopovers.

Input

The first line of input contains a single number indicating the number of scenarios to process. A blank line precedes each scenario.

Each scenario begins with a number N (2 ≤ N ≤ 100), the number of cities, followed by N lines containing the names of the cities. A city name is a string of up to 20 uppercase and lowercase letters. Next is a number M (0 ≤ M ≤ 1000), the number of flights available, followed by M lines describing the flights. Each flight is described by its departure city, its destination city, and an integer representing its cost in dollars. The final line starts with Q (1 ≤ Q ≤ 10), the number of queries, followed by Q numbers indicating the maximum number of stopovers.

Output

For each scenario, your program should output the scenario number, followed by the least total cost of the flights for each query. Follow the format of the sample output. If no flights can satisfy a query, write "No satisfactory flights". Output a blank line between scenarios.

Sample Input

2

4
Calgary
Winnipeg
Ottawa
Fredericton
6
Calgary Winnipeg 125
Calgary Ottawa 300
Winnipeg Fredericton 325
Winnipeg Ottawa 100
Calgary Fredericton 875
Ottawa Fredericton 175
3 2 1 0

3
Calgary
Montreal
Fredericton
2
Calgary Montreal 300
Montreal Fredericton 325
1 0

Output for the Sample Input

Scenario #1
Total cost of flight(s) is $400
Total cost of flight(s) is $450
Total cost of flight(s) is $875

Scenario #2
No satisfactory flights

Brett Shikaze
Calgary Collegiate Programming Contest 2006


题意:给出n个城市和m条航线,每条航线连接两个城市,一个是航线的出发城市,一个是航线的抵达城市,并且有相应的花费。给出起点和目的地城市,然后有Q个询问,每个询问给出在起点和目的地城市路线中间最大可经过的城市数目,问在中间经过的城市数要小于等于最大可经过的城市数目的条件下,从指定的该起点城市到目的地城市的花费最少是多少。如果在该条件限制下不能抵达目的地,输出“No satisfactory flights”。


解题思路:要用二维来表示状态。一维表示到达某个城市的最短路径(也就是题目中的花费),第二维表示到达某个城市时中间经过的城市数目。同时该题输入数据比较麻烦,要用一些技巧对输入的数据进行处理,还要注意查询时输入数据可能不是合法的,这个也是一大坑点,要对数据判断后处理。剩下的就是裸的SPFA了。


AC code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
#include<cmath>
#define LL long long
#define MAXN 1000010
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,tot;
int head[MAXN];
struct state{//用结构体来表示当前的状态:当前到达的城市编号为city,经过停留的城市数为stop 
	int city;
	int stop;
};
struct node{
	int from;
	int to;
	int w;
	int next;
}edge[MAXN];
int dis[111][111];
bool inq[111][111];
int cnt[111][111];
void init()
{
	memset(head,-1,sizeof(head));
	tot=0;
}
void add(int from,int to,int w)
{
	edge[tot].from=from;
	edge[tot].to=to;
	edge[tot].w=w;
	edge[tot].next=head[from];
	head[from]=tot++;
}
bool spfa(int start,int ed)
{
	deque<state>q;
	memset(dis,INF,sizeof(dis));
	memset(inq,false,sizeof(inq));
	memset(cnt,0,sizeof(cnt));
	state st;
	st.city=start;
	st.stop=0;
	dis[st.city][st.stop]=0;
	q.push_back(st);
	inq[st.city][st.stop]=true;
	cnt[st.city][st.stop]++;
	while(!q.empty())
	{
		state now=q.front();
		q.pop_front();
		inq[now.city][now.stop]=false;
		if(cnt[now.city][now.stop]>n)
		{
			continue;
		}
		if(cnt[now.city][now.stop]==n)
		{
			dis[now.city][now.stop]=INF;
		}
		for(int i=head[now.city];i!=-1;i=edge[i].next)
		{
			state nex;
			nex.city=edge[i].to;
			nex.stop=now.stop+1;
			if(dis[nex.city][nex.stop]>dis[now.city][now.stop]+edge[i].w)
			{
				dis[nex.city][nex.stop]=dis[now.city][now.stop]+edge[i].w;
				if(!inq[nex.city][nex.stop])
				{
					state front=q.front();
					if(!q.empty()&&dis[nex.city][nex.stop]<dis[front.city][front.stop])
					{
						q.push_front(nex);
					}
					else
					{
						q.push_back(nex);
					}
				}
			}
		}
	}
	return true;
}
int main()
{
	//freopen("D:\in.txt","r",stdin);
	int T,cas,i,j,u,v,w,Q,s,ans;
	scanf("%d",&T);
	for(cas=1;cas<=T;cas++)
	{
		scanf("%d",&n);
		map<string,int>city;
		string name1,name2;
		for(i=1;i<=n;i++)
		{
			cin>>name1;//一大坑点,输入的不是城市编号,是城市名,要用map巧妙地
			city[name1]=i;//将字符串的城市名转化为数值类型的城市编号  
		}
		scanf("%d",&m);
		init();
		while(m--)
		{
			cin>>name1>>name2>>w;
			add(city[name1],city[name2],w);
		}
		int start=city["Calgary"];
		int ed=city["Fredericton"];
		spfa(start,ed);
		scanf("%d",&Q);
		printf("Scenario #%d\n",cas);
		while(Q--)
		{
			scanf("%d",&s);
			s=min(s,n-2);//一大坑点!!!输入的可停留次数可能超出合法范围,必须自己做处理!!! 
			ans=INF;
			for(i=0;i<=s;i++)
				ans=min(ans,dis[n][i+1]);
			if(ans>=INF)
			{
				printf("No satisfactory flights\n");
			}
			else
			{
				printf("Total cost of flight(s) is $%d\n",ans);
			}
		}
		if(cas!=T)
		{
			printf("\n");
		}
	}
	return 0;
 } 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值