Link:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25133
Description
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;
}