题目:
n个城市之间有m条双向路。每条路要耗费一定的油量。每个城市的油价是固定并且已经给出的。有q个询问,表示从城市s走到e,油箱的容量为c,求最便宜的方案。
思路:
可以分层图最短路,有点类似DP的思想
按油量分层,dis[i][j]表示到节点i还有j个油的最小花费(不是最短路)
两种决策,加一个油或者直接走
需要比较好的剪枝,不然会超时,可以离线,每次不用更新所有可能的油量,更新比其大一的即可
代码如下
/*
* Author : Echo
* Email : 1666424499@qq.com
* Description :
* Created Time : 2017/10/7 8:43:20
* Last Modify : 2017/10/7 17:57:49
* File Name : a.cpp
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int INF =1e9;
const int maxn=1e3+100;
const int maxm=2e4+100;
struct edge{
int to,next;
int value;
void set(int a,int b,int c){
to=a,value=b,next=c;
}
}bn[maxm];
int head[maxn],cnt=0;
void addedge(int u,int v,int value){
bn[cnt].set(v,value,head[u]);
head[u]=cnt++;
}
int an[maxn];
int dis[maxn][110];
bool vis[maxn][110];
int minn(int a,int b){
return a<b? a:b;
}
struct node{
int u,flow,dis;
friend bool operator <(node a,node b){
return a.dis>b.dis;
}
};
int dijkstra(int s,int t,int cap,int n){
for(int i=0;i<n;i++)
for(int j=0;j<=cap;j++){
dis[i][j]=INF;
vis[i][j]=0;
}
priority_queue<node>que;
dis[s][0]=0;
node now,nxt;
now.u=s;
now.flow=0;
now.dis=0;
que.push(now);
while(!que.empty()){
now=que.top();
que.pop();
int u=now.u;
int flow=now.flow;
if(u==t) return now.dis;
if(now.dis>dis[u][flow]||vis[u][flow]) continue;
vis[u][flow]=1;
if(flow<cap&&dis[u][flow+1]>now.dis+an[u]){
dis[u][flow+1]=now.dis+an[u];
nxt.u=u;
nxt.flow=flow+1;
nxt.dis=dis[u][flow+1];
que.push(nxt);
}
for(int i=head[u];i!=-1;i=bn[i].next){
if(flow<bn[i].value) continue;
int v=bn[i].to;
int vrem=flow-bn[i].value;
if(dis[v][vrem]>now.dis){
dis[v][vrem]=now.dis;
nxt.u=v;
nxt.flow=vrem;
nxt.dis=dis[v][vrem];
que.push(nxt);
}
}
}
return -1;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
head[i]=-1;
}
cnt=1;
for(int i=0;i<n;i++) scanf("%d",&an[i]);
for(int i=1;i<=m;i++){
int a,b,value;
scanf("%d%d%d",&a,&b,&value);
addedge(a,b,value);
addedge(b,a,value);
}
int cs;
cin>>cs;
while(cs--){
int a,b,c;
scanf("%d%d%d",&c,&a,&b);
int ans=dijkstra(a,b,c,n);
if(ans>=0)
printf("%d\n",ans);
else printf("impossible\n");
}
return 0;
}
/*
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
170
impossible
*/