Time Limit: 2 second(s) | Memory Limit: 32 MB |
Michael Scofield has just broken out of the prison. Now he wants to go to a certain city for his next unfinished job. As you are the only programmer on his gang, he asked your help. As you know that the fuel prices vary in the cities, you have to write a code to help Scofield that instructs him where to take the fuel and which path to choose. Assume that his car uses one unit of fuel in one unit of distance. Now he gives you the starting city s where he starts his journey with his car, the destination city t and the capacity of the fuel tank of his car c, the code should find the route that uses the cheapest fuel cost. You can assume that Scofield's car starts with an empty fuel tank.
Input
Input starts with an integer T (≤ 5), denoting the number of test cases.
Each case starts with a line containing two integers n (2 ≤ n ≤ 100) and m (0 ≤ m ≤ 1000) where n denotes the number of cities and m denotes the number of roads. The next line contains n space separated integers, each lies between 1 and 100. The ith integer in this line denotes the fuel price (per unit) in the ithcity. Each of the next m lines contains three integers u v w (0 ≤ u, v < n, 1 ≤ w ≤ 100, u ≠ v) denoting that there is a road between city u and v whose length is w.
The next line contains an integer q (1 ≤ q ≤ 100) denoting the number of queries by Scofield. Each of the next q lines contains the request. Each request contains three integers: c s t (1 ≤ c ≤ 100, 0 ≤ s, t < n) where c denotes the capacity of the tank, s denotes the starting city and t denotes the destination city.
Output
For each case, print the case number first. Then for each query print the cheapest trip from s to t using the car with the given capacity c or 'impossible' if there is no way of getting from s to t with the given car.
Sample Input | Output for Sample Input |
1 5 5 10 10 20 12 13 0 1 9 0 2 8 1 2 1 1 3 11 2 3 7 2 10 0 3 20 1 4 | Case 1: 170 impossible |
题意:n个点m条边的有向图,q次询问c,s,t,表示汽车邮箱容量为c,求从起点s到终点t的最小费用。汽车在每个点可以加任意的油,每个点的油价为a[i]。
思路:优先队列的Dij,每个节点保存还剩下的油量fuel和到当前为止所用的花费,dis[i][j]表示在i点油量还剩下j的费用最小值。注意,每次入队列不要一次性把所有符合的油量全部入队列,比如u->v,距离为w,那么油量区间w~c之间的油量都是可以满足从u走到v的,但不要一次性把w~c全部入队列,这样会超时:应该这样:对于队列中的每个点u先看它当前的油量能否顺着边走到下一个节点v去更新v,如果可以就更新v,然后当前点u的油量还可以增加就把它的油量增加一再入队列。
代码:
#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v) memset ((t) , v, sizeof(t))
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf printf
#define DBG pf("Hi\n")
typedef long long ll;
using namespace std;
#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 105;
const int MAXM = 200010;
const int N = 1005;
struct Node
{
int id,fuel,cost;
Node(){}
Node(int a,int b,int c):id(a),fuel(b),cost(c){}
bool operator<(Node a) const
{
return cost>a.cost;
}
}node[MAXN];
struct Edge
{
int u,v,w,next;
}edge[MAXM];
int n,m,c,s,t;
int num,head[MAXN],dis[MAXN][MAXN];
int a[MAXN];
void init()
{
num=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
edge[num].u=u;
edge[num].v=v;
edge[num].w=w;
edge[num].next=head[u];
head[u]=num++;
}
void Dijkstra(int c,int s,int t)
{
int u,v;
Node st,now;
priority_queue<Node>Q;
memset(dis,INF,sizeof(dis));
dis[s][0]=0;
Q.push(Node(s,0,0));
while (!Q.empty())
{
st=Q.top();
Q.pop();
u=st.id;
if (dis[u][st.fuel]<st.cost) continue;
for (int i=head[u];~i;i=edge[i].next)
{
v=edge[i].v;
if (st.fuel>=edge[i].w&&dis[v][st.fuel-edge[i].w]>dis[u][st.fuel]) //更新下一个节点
{
dis[v][st.fuel-edge[i].w]=dis[u][st.fuel];
Q.push(Node(v,st.fuel-edge[i].w,dis[u][st.fuel]));
}
}
if (st.fuel<c&&dis[u][st.fuel+1]>dis[u][st.fuel]+a[u]) //当前点的油量还可以增加1
{
dis[u][st.fuel+1]=dis[u][st.fuel]+a[u];
Q.push(Node(u,st.fuel+1,dis[u][st.fuel]+a[u]));
}
}
int ans=INF;
for (int i=0;i<=c;i++)
ans=min(dis[t][i],ans);
if (ans==INF) printf("impossible\n");
else printf("%d\n",ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
int i,j,e,u,v,w,q,cas=0;
scanf("%d",&e);
while (e--)
{
scanf("%d%d",&n,&m);
for (i=0;i<n;i++) scanf("%d",&a[i]);
init();
for (i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
scanf("%d",&q);
printf("Case %d:\n",++cas);
while (q--)
{
scanf("%d%d%d",&c,&s,&t);
Dijkstra(c,s,t);
}
}
return 0;
}