//Memory 15984K Time 891MS
#include <iostream>
#include <cstdio>
#include <list>
#include <queue>
using namespace std;
int cityNum;//城市数量
int roadNum;//城市之间的道路数量
//到达顶点v需要消耗的汽油oil
struct ArriveGoalNode {
int v, oil;
};
//ver[currarriveGoalNode.u].arcs.begin()
//城市加油的结构体
struct VertexInfo {
int oilCost;//在当前城市加油需要的费用
//从当前城市出发到达另外的城市
list<ArriveGoalNode> arcs;
} *verNum;//存储城市信息的一维数组
//汽车的当前状态
struct State {
//汽车当前所在的城市
int nowCity;
//汽车当前加油
//累加消耗的费用
int cost;
//汽车当前的剩余汽油量
int restOil;
//重载小于运算符
//使汽车的状态结构体对象
//能够调整优先级
//使当前汽车累加消耗的最少费用节点
//处在优先队列的对首
bool operator<(const State &obj) const {
return cost > obj.cost;
}
};
//构造从a城市到达b城市,并且需要消耗oil油量的边
void createEdge(int a, int b, int oil) {
ArriveGoalNode arc;
arc.v = b;
arc.oil = oil;
//从城市a出发到达城市b
//将城市b节点加到城市a对应的arcs
verNum[a].arcs.push_back(arc);
}
//bfs(maxCapacity, s, e, ans)
void bfs(int capacity, int beginCity, int endCity, int &optimal) {
priority_queue<State> pq;
//isVisit[i][j]到达加油站i,油箱剩余油量为j
//当前累加加油费用
//初始化记录数组
int **isVisit = new int *[cityNum];
for (int i = 0; i < cityNum; i++)
isVisit[i] = new int[capacity + 1];
//初始化每行的每一列
for (int i = 0; i < cityNum; i++)
fill(isVisit[i], isVisit[i] + capacity + 1, 1 << 20);
//初始化汽车开始状态
State beginState;
beginState.nowCity = beginCity;
beginState.restOil = 0;
beginState.cost = 0;
pq.push(beginState);
isVisit[beginState.nowCity][beginState.restOil] = 0;
//队列不为空
while (!pq.empty()) {
//取出对首数据
State nowState = pq.top();
pq.pop();
//到达目标地点(到达叶子节点)
if (nowState.nowCity == endCity) {
//将当前已经累加的最少加油费用赋值给ans
optimal = nowState.cost;
return;
}
//加油过程
//当前汽车的油量未达到油箱最大容量
//并且汽车目前加油累加的消耗费用,加上在当前城市加油消耗的费用
//小于在当前城市加了一个单位的油后的最小费用
if (nowState.restOil < capacity &&
nowState.cost + verNum[nowState.nowCity].oilCost < isVisit[nowState.nowCity][nowState.restOil + 1]) {
State temPoraryState;
temPoraryState.nowCity = nowState.nowCity;
//在当前城市加一个单位的油
temPoraryState.restOil = nowState.restOil + 1;
//累加在当前城市加一个单位的油,的费用
temPoraryState.cost = nowState.cost + verNum[nowState.nowCity].oilCost;
pq.push(temPoraryState);
isVisit[temPoraryState.nowCity][temPoraryState.restOil] = temPoraryState.cost;
}
//出发过程
//遍历以当前城市为起点,可到达的城市
for (list<ArriveGoalNode>::iterator it = verNum[nowState.nowCity].arcs.begin();
it != verNum[nowState.nowCity].arcs.end(); it++)
//当前汽车剩余油量大于从a顶点到达第一个与a相连的顶点之间的权值(即需要消耗的油量)
//当前汽车已经累加的加油费用小于到达加油站v(在油量剩余为出发前的油量减去路途消耗的油量)的最小累加加油费用
//即汽车可以从顶点u到达顶点v
//并且可能找到更好的解
//isVisit[i][j]到达加油站i,油箱剩余油量为j
//当前累加加油费用
if (nowState.restOil >= it->oil &&
nowState.cost < isVisit[it->v][nowState.restOil - it->oil]) {
State finalState;
//更新节点信息
finalState.nowCity = it->v;
finalState.restOil = nowState.restOil - it->oil;
finalState.cost = nowState.cost;
pq.push(finalState);
isVisit[finalState.nowCity][finalState.restOil] = finalState.cost;
}
}
//释放内存
for (int i = 0; i < cityNum; i++)
delete[] isVisit[i];
delete[] isVisit;
}
int main() {
//录入城市数量和城市之间的道路数量
while (~scanf("%d%d", &cityNum, &roadNum)) {
//城市节点信息
verNum = new VertexInfo[cityNum];
for (int i = 0; i < cityNum; i++)
//录入每个城市加油需要的费用
scanf("%d", &verNum[i].oilCost);
//录入城市之间的道路
//(从a城市到达b城市需要消耗的油量为oil)
for (int i = 0; i < roadNum; i++) {
int a, b, oil;
scanf("%d%d%d", &a, &b, &oil);
//构造虚拟图中的a顶点到b顶点的边
//边的权值对应a顶点到b顶点需要消耗的油量
createEdge(a, b, oil);
createEdge(b, a, oil);
}
//查询数量的录入
int queryNum;
scanf("%d", &queryNum);
//录入具体的每条查询的信息
//即汽车在油箱容量最大为maxCapacity
//是否能从a城市到达b城市
for (int i = 0; i < queryNum; i++) {
int maxCapacity, beginCity, endCity;
scanf("%d%d%d", &maxCapacity, &beginCity, &endCity);
int optimal = 1 << 30;
//ans存储汽车在maxCapacity的最大油箱容量
//从a城市到达b城市,如果可行的最少加油费用
bfs(maxCapacity, beginCity, endCity, optimal);
optimal == 1 << 30 ? printf("impossible\n") : printf("%d\n", optimal);
}
}
//释放内存
delete[] verNum;
return 0;
}
//简洁版
#include <iostream>
#include <cstdio>
#include <list>
#include <queue>
using namespace std;
struct ArriveGoalNode {
int v;
int oil;
};
struct VertexInfo {
int oilCost;
list<ArriveGoalNode> arcs;
};
struct State {
int nowCity;
int restOil;
int cost;
bool operator<(const State &obj) const {
return cost > obj.cost;
}
};
int cityNum;
int roadNum;
VertexInfo *verNum;
void createEdge(int a, int b, int oil) {
ArriveGoalNode arc;
arc.v = b;
arc.oil = oil;
verNum[a].arcs.push_back(arc);
}
void bfs(int capacity, int beginCity, int endCity, int &optimal) {
priority_queue<State> pq;
int **isVisit = new int *[cityNum];
for (int i = 0; i < cityNum; i++)
isVisit[i] = new int[capacity + 1];
for (int i = 0; i < cityNum; i++)
fill(isVisit[i], isVisit[i] + capacity + 1, 1 << 20);
State beginState;
beginState.nowCity = beginCity;
beginState.restOil = 0;
beginState.cost = 0;
pq.push(beginState);
isVisit[beginState.nowCity][beginState.restOil] = 0;
while (!pq.empty()) {
State nowState = pq.top();
pq.pop();
if (nowState.nowCity == endCity) {
optimal = nowState.cost;
return;
}
if (nowState.restOil < capacity &&
nowState.cost + verNum[nowState.nowCity].oilCost < isVisit[nowState.nowCity][nowState.restOil + 1]) {
State temPoraryState;
temPoraryState.nowCity = nowState.nowCity;
temPoraryState.restOil = nowState.restOil + 1;
temPoraryState.cost = nowState.cost + verNum[nowState.nowCity].oilCost;
pq.push(temPoraryState);
isVisit[temPoraryState.nowCity][temPoraryState.restOil] = temPoraryState.cost;
}
for (auto it = verNum[nowState.nowCity].arcs.begin(); it != verNum[nowState.nowCity].arcs.end(); it++)
if (nowState.restOil >= it->oil &&
nowState.cost < isVisit[it->v][nowState.restOil - it->oil]) {
State finalState;
finalState.nowCity = it->v;
finalState.restOil = nowState.restOil - it->oil;
finalState.cost = nowState.cost;
pq.push(finalState);
isVisit[finalState.nowCity][finalState.restOil] = finalState.cost;
}
}
for (int i = 0; i < cityNum; i++)
delete[] isVisit[i];
delete[] isVisit;
}
int main() {
while (~scanf("%d%d", &cityNum, &roadNum)) {
verNum = new VertexInfo[cityNum];
for (int i = 0; i < cityNum; i++)
scanf("%d", &verNum[i].oilCost);
for (int i = 0; i < roadNum; i++) {
int a, b, oil;
scanf("%d%d%d", &a, &b, &oil);
createEdge(a, b, oil);
createEdge(b, a, oil);
}
int queryNum;
scanf("%d", &queryNum);
for (int i = 0; i < queryNum; i++) {
int maxCapacity, beginCity, endCity;
scanf("%d%d%d", &maxCapacity, &beginCity, &endCity);
int optimal = 1 << 30;
bfs(maxCapacity, beginCity, endCity, optimal);
optimal == 1 << 30 ? printf("impossible\n") : printf("%d\n", optimal);
}
}
delete[] verNum;
return 0;
}