emm

liuzhenchao 2020-07-25 9:15:44

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1010,M=10010;//定义数组用 
int head[N],nxt[M<<1],to[M<<1],w[M<<1],tot;//链式前向星存图用;
int n,m,q;
int val[N];//每个城市的油价 
int c,s,e;//每次询问给出的容量,起点,终点;
int v[N][110],dist[N][110];//v数组表示某状态是否入过堆,dist数组表示到达此状态当前搜索到的最小花费 
struct edge{
	int dis; //当前油费
	int x;//当前所处位置
	int c;//当前油量 
};//定义结构体方便表示状态 
bool operator<(const edge &a,const edge &b)
{
	return a.dis>b.dis;
}//重载运算符,根据油费排列小根堆,不会写小根堆的参数qwq 
void add(int x,int y,int c)
{
	to[++tot]=y;
	w[tot]=c;
	nxt[tot]=head[x];
	head[x]=tot;
}//加边函数 
int dijkstra(int c,int start,int end)//c表示油箱容量(油量的最大值),start记录出发点, end记录目标点 
{ 
	priority_queue<edge>que;  
	memset(dist,0x3f,sizeof(dist));//多次询问,需要初始化,要 /求最小值,初始化成极大值 
	memset(v,0,sizeof(v));//初始化 
	que.push((edge){0,start,0});//还是初始化,ps:油箱初始为空 
	dist[start][0]=0;
	while(que.empty()!=1)
	{
		edge q=que.top();//是堆 ,用top()而不是front(); 
		que.pop();//不加pop()见祖宗; 
		if(q.x==end&&q.c==0)return q.dis;//由于是根据dis(油费) 排列的小根堆,且无负边权,搜索到的第一个到达目标点的即为最优解 
		if(v[q.x][q.c])continue;//emmm,原因同上 ,就不用再搜了 
		v[q.x][q.c]=1;//改v留下证据:已搜过 
		if(q.c<c)//油箱没满,加一升 
		{
			if(dist[q.x][q.c+1]>q.dis+val[q.x])
			{
				dist[q.x][q.c+1]=q.dis+val[q.x];
				que.push((edge){q.dis+val[q.x],q.x,q.c+1});	
			}//更新后入堆 
		}
		for(int i=head[q.x];i;i=nxt[i])
		{
			int y=to[i];
			if(q.c>=w[i])//油足够跑到下一座城市 
			{
				if(dist[y][q.c-w[i]]>q.dis)
				{
					dist[y][q.c-w[i]]=q.dis;
					que.push((edge){q.dis,y,q.c-w[i]});
				}//更新后入堆 
			}
		}
	}
	return -1;//一顿搜索没找到,返回-1; 
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		cin>>val[i];//从0编号 
	}
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);//无向图双向建边; 
	}
	cin>>q;
	while(q--)//多组询问; 
	{
		cin>>c>>s>>e;
		int t=dijkstra(c,s,e); 
		if(t==-1)
		{
			cout<<"impossible"<<endl;
		}
		else cout<<t<<endl;
	}
	return 0;
}

共 1 条回复

admin

tql