版权声明:Power by PowderHan https://blog.csdn.net/weixin_42827051/article/details/83113886
Full Tank
POJ - 3635
题目传送门
题目大意
有n个城市和m条道路(n<=1000 m<=10000),构成一张无向图。在每个城市里面有一个加油站,不同加油站加个不同。通过一条道路的油耗就是该道路的边权。现在给q个询问(q<=100),每次提问给出c为油箱最大容量,s为起点,t为终点。求s到t至少需要花多少油钱?(初始时油箱为空)
思路
这是一道边权不全为1的bfs题。在这个状态图中不同状态的转移价值不同,因此我们不能使用普通的bfs来完成,而可以使用优先队列来完成,保证队列中的状态的花费具有单调性。那么第一次终点t出队时就是它的最小花费。
优先队列保证花费最小的状态先出队。
首先我们考虑一个状态可以用(city,fuel)来表示,即只需要记录其当前所在城市和当前剩余油量,这样即可有效判重。这样对于每一个状态,我们有两种扩展方式
1.如果fuel<c,那么我们可以加一升油,并将新状态(city,fuel+1)入队(通过很多次的fule+1可以加到任意值),同时花费cost[city]
2,对于每条从当前city出发的边,如果当前fule>w边权,则前往下一个城市,并入队(next,fule-w)
这样我们不断的取出优先队列队首(顶)的元素进行扩展,当t第一次被取出时就是最小的花费
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int MAXN=1005;
const int MAXM=20005;
const int MAXW=10005;
struct Edge
{
int to,nxt;
int w;
}e[MAXM];
int first[MAXN];
int minw[MAXN];
int g[MAXN];
int n,m;
int tot;
int t;
inline void Add_Edge(const int& u,const int& v,const int& w)
{
e[++tot].to=v; e[tot].w=w;
e[tot].nxt=first[u]; first[u]=tot;
}
void init()
{
memset(first,-1,sizeof(first));
memset(minw,0x3f,sizeof(minw));
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%d",&g[i]);
int x,y,w;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&w);
x++; y++;
Add_Edge(x,y,w); Add_Edge(y,x,w);
minw[x]=min(minw[x],w); minw[y]=min(minw[y],w);
}
}
struct Point
{
int pos;
int fule;
int cost;
bool operator<(const Point& p)const
{
return cost>p.cost;
}
};
bool vis[MAXN][MAXW];
void bfs(int c,int s,int t)
{
memset(vis,0,sizeof(vis));
Point S={s,0,0};
priority_queue<Point> q;
while(!q.empty())
q.pop();
q.push(S);
vis[s][0]=1;
while(!q.empty())
{
Point now=q.top(); q.pop();
int& u=now.pos;
int& fule=now.fule; int& cost=now.cost;
vis[u][fule]=1;
//cout<<u<<" "<<fule<<" "<<cost<<endl;
if(u==t)
{
printf("%d\n",cost);
return;
}
if(fule<c)
q.push((Point){u,fule+1,cost+g[u]});
for(int i=first[u];i!=-1;i=e[i].nxt)
{
int& v=e[i].to; int & w=e[i].w;
if(fule<w)
continue;
if(!vis[v][fule-w])
q.push((Point){v,fule-w,cost});
}
}
printf("impossible\n");
}
void work()
{
cin>>t;
int c,x,y;
while(t--)
{
scanf("%d%d%d",&c,&x,&y);
x++; y++;
bfs(c,x,y);
}
}
int main()
{
init();
work();
return 0;
}