题意:每个城市的油价可能不相同,求从一个城市到另外一个城市的最小花费
这个题目第一个解法用的是spfa,求出每个顶点的d[i][j],到达第i个城市,剩余j油量的最小花费,t了
然后开始加入一些剪枝,第一个剪枝,当当前费用已经大于到达目标点的估计费用时,不在拓展
第二个剪枝,当前点的油量不足以到达其他任何一个城市时,只加油,不再枚举每条边
第三个:对第一个剪枝的优化,对当前点的费用加上最优惠油价乘以离目标最短距离大于到达目标点的估计值时,退出。这样已经可以再规定时间内算出解了
第二个解法:dijkstra的宽搜解法,用堆维护队列,当某个状态出列时,它必定是最优的,这个之前已经说过了,不再累叙。
错误,把每个顶点的花费直接用d[][]里边的值来代替,刚开始这么做的原因是因为可以省空间
但是错误出现了,有可能同一个状态的最优解会被更新多次,刚开始已经意识到了这一点,但是当时认为这样只是第二次更新的时候用了更优的解来更新罢了,并没有影响,但是它却影响了队列的性质,由于其中的某个值突然改变,破坏了堆的结构,所以不能保证每次出列的依然是最优的解。
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
const int inf=1<<30;
const int maxn=1001;
int n,m;
int price[maxn],dist[maxn][101];
struct node
{
intto,dist;
struct node*next;
}e[maxn],*p;
struct
{
intdata,c,cost;
}queue[2000001];
int swap(int a,int b)
{
intt=queue[a].data,tmp=queue[a].c,cost=queue[a].cost;
queue[a].data=queue[b].data,queue[a].c=queue[b].c,queue[a].cost=queue[b].cost;
queue[b].data=t,queue[b].c=tmp,queue[b].cost=cost;
}
int adjustup(int n)
{
inti=n,j;
while(i/2>=1)
{
j=i/2;
if(queue[j].cost<=queue[i].cost) break;
swap(i,j);
i=j;
}
}
int adjustdown(int n)
{
inti=1,j;
while(i*2<=n)
{
j=i*2;
if(j+1<=n&&queue[j].cost>queue[j+1].cost)j++;
if(queue[i].cost<=queue[j].cost) break;
swap(i,j);
i=j;
}
}
int dijkstra(int c,int from,int to)
{
intfront=1,end=1;
for(inti=1;i<=n;i++)
for(intj=0;j<=c;j++)
dist[i][j]=inf;
dist[from][0]=0;
queue[front].data=from;
queue[front].cost=0;
queue[front].c=0;
while(front<=end)
{
// for(int i=front;i<=end;i++)
// printf("%d ",dist[queue[i].data][queue[i].c]);
// printf("\n");
int t=queue[front].data,tmp=queue[front].c;
swap(1,end);
adjustdown(--end);
if(t==to) break;
if(tmp+1<=c&&dist[t][tmp+1]>dist[t][tmp]+price[t])
{
dist[t][tmp+1]=dist[t][tmp]+price[t];
queue[++end].data=t;
queue[end].c=tmp+1;
queue[end].cost=dist[t][tmp+1];
adjustup(end);
}
p=e[t].next;
while(p!=&e[t])
{
if(tmp>=p->dist&&dist[p->to][tmp-p->dist]>dist[t][tmp])
{
dist[p->to][tmp-p->dist]=dist[t][tmp];
queue[++end].data=p->to;
queue[end].c=tmp-p->dist;
queue[end].cost=dist[p->to][tmp-p->dist];
adjustup(end);
}
p=p->next;
}
}
}
int edgeini(int n)
{
for(inti=1;i<=n;i++)
e[i].next=&e[i];
}
int edgemake(int from,int to,int dist)
{
p=(structnode*)malloc(sizeof(struct node));
p->next=e[from].next;
e[from].next=p;
p->to=to;
p->dist=dist;
}
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(inti=1;i<=n;i++) scanf("%d",&price[i]);
edgeini(n);
for(inti=1;i<=m;i++)
{
int from,to,dist;
scanf("%d %d%d",&from,&to,&dist);
from++,to++;
edgemake(from,to,dist);
edgemake(to,from,dist);
}
intq;scanf("%d",&q);
for(inti=1;i<=q;i++)
{
int c,from,to;
scanf("%d %d%d",&c,&from,&to);
from++,to++;
dijkstra(c,from,to);
if(dist[to][0]==inf)
printf("impossible\n");
else
printf("%d\n",dist[to][0]);
}
return0;
}