Full Tank? POJ - 3635

版权声明: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;	
}

猜你喜欢

转载自blog.csdn.net/weixin_42827051/article/details/83113886