今天螳螂打野坑爆全场,所以刷题状态也是十分不好。。。
题目大意就是说,一个加油车在每个点可以加油,但不能超过给定油箱容量,给出每两个点之间的路径也就是耗油数量,而每个点油价也是不同,计算出S点到E点之间最短话费。。。
思路:最短路径,只不过把路径换成耗油量,即在每个点可以选择加油或者继续往其他点开(只要油量够)。。。所以对每个点进行拆点,可以选择加一升油,或者继续前进。。。最多一千个点,一百升油,所以最大十万个点,对于时间复杂度有一定要求,所以本题用优先队列优化dijkstra算法,由于只用计算出S点到E的最少话费而不是计算出到所有点的最少话费,所以相对于SPFA算法更好。
#include<cstdio>
#include<cstring >
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1005;
int price[maxn],head[maxn],vis[maxn][105];
int n,m,cnt;
struct node{
int v,w,next;
}node[maxn*20];
struct point{
int u,oil,cost;
};
bool operator < (const point a,const point b){
return a.cost > b.cost;
}
void addedge(int u,int v,int c){
node[cnt].v=v; node[cnt].w=c; node[cnt].next=head[u];
head[u]=cnt++;
node[cnt].v=u; node[cnt].w=c; node[cnt].next=head[v];
head[v]=cnt++;
}
void dijkstra(int capacity,int s,int e){
memset(vis,0,sizeof(vis));
priority_queue<point> q;
point start;
start.u=s; start.oil=0; start.cost=0;
q.push(start);
while(!q.empty()){
point hd=q.top();
q.pop();
int u=hd.u; int oil=hd.oil;
vis[u][oil]=1;
if(u==e){
printf("%d\n",hd.cost);
return;
}
if(hd.oil<capacity&&!vis[u][oil+1]){
point t;
t.u=u;
t.oil=oil+1;
t.cost=hd.cost+price[u];
q.push(t);
}
for(int i=head[u];i!=-1;i=node[i].next){
if(hd.oil>=node[i].w&&!vis[node[i].v][hd.oil-node[i].w]){
point t;
t.u=node[i].v;
t.oil=hd.oil-node[i].w;
t.cost=hd.cost;
q.push(t);
}
}
}
printf("impossible\n");
}
int main()
{
//freopen("3635.txt","r",stdin);
int u,v,c;
while(~scanf("%d %d",&n,&m)){
cnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<n;i++)
scanf("%d",&price[i]);
while(m--){
scanf("%d %d %d",&u,&v,&c);
addedge(u,v,c);
}
int q,capacity,s,e;
cin>>q;
while(q--){
scanf("%d %d %d",&capacity,&s,&e);
dijkstra(capacity,s,e);
}
}
return 0;
}