[PTA] L2-001 Emergency Rescue (25 points) [dijkstra+ priority queue optimization]

As the head of a city’s emergency rescue team, you have a special map of the country. On the map, there are multiple scattered cities and some express roads connecting the cities. The number of rescue teams in each city and the length of each expressway connecting the two cities are marked on the map. When other cities have emergency calls to you, your task is to lead your rescue team as soon as possible to the place where the incident occurred, and at the same time, gather as many rescue teams as possible along the way.

Input format:
Input the first line to give 4 positive integers N, M, S, D, where N (2≤N≤500) is the number of cities. By the way, assume that the number of the city is 0 ~ (N−1); M is the number of expressways; S is the city number of the departure place; D is the city number of the destination.

The second line gives N positive integers, where the i-th number is the number of rescue teams in the i-th city, and the numbers are separated by spaces. In the subsequent M lines, each line gives information about an express road, namely: city 1, city 2, and the length of the express road, separated by spaces, and the numbers are all integers and do not exceed 500. The input ensures that the rescue is feasible and the optimal solution is unique.

Output format: The
first line outputs the number of shortest paths and the maximum number of rescue teams that can be assembled. The second line outputs the number of the city passed in the path from S to D. The numbers are separated by spaces, and there should be no extra spaces at the end of the output.

Input sample:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

Sample output:

2 60
0 1 3

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
    
    
	int v,w;
	node(int a,int b){
    
    v=a;w=b;}
	friend bool operator<(node a,node b){
    
    
		return a.w>b.w;
	}
};

const int maxn = 550;
const int inf = 1<<27; //表示无穷远,到不了
//p各地救援队,num路径数,dis最短距离,ans最大救援队,pre前驱节点
int n,m,s,d,a,b,len,p[maxn]={
    
    0},num[maxn]={
    
    0},dis[maxn],ans[maxn]={
    
    0},pre[maxn];
vector<node> g[maxn];
bool vis[maxn]={
    
    false}; //标记是否入过队

void print() //先放入栈中,再进行输出
{
    
    
	stack<int> s;
	s.push(d);
	while(pre[d]!=-1){
    
    
		s.push(pre[d]);
		d=pre[d];
	} 
	
	while(s.size())
	{
    
    
		cout<<s.top();
		s.pop();
		if(s.size()) cout<<" ";
	}
}

void dijk()
{
    
    
	fill(dis,dis+maxn,inf); //初始化距离为无穷远,表示到不了
	priority_queue<node> q;
	dis[s]=0; //起点距离起点0
	num[s]=1; //一条路径
	ans[s]=p[s]; //起点的最大救援队等于起点的救援队数
	pre[s]=-1; //设置起点的前驱节点为-1
	q.push(node(s,0));
	while(!q.empty())
	{
    
    
		int u=q.top().v;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1; //标记入队
		for(int i=0;i<g[u].size();i++)
		{
    
    
			int v=g[u][i].v;
			int w=g[u][i].w;
			if(!vis[v]) //没入过队
			{
    
    
				if(dis[v]>dis[u]+w) //可以更新距离
				{
    
    
					pre[v]=u;
					dis[v]=dis[u]+w;
					ans[v]=ans[u]+p[v];
					num[v]=num[u];
				}
				else if(dis[v]==dis[u]+w) //距离相等
				{
    
    	
					if(ans[v]<ans[u]+p[v]) //可以更新最大救援队
					{
    
    
						pre[v]=u;
						ans[v]=ans[u]+p[v];
					}	
					num[v]+=num[u]; //累加路径条数
				}	
				q.push(node(v,dis[v]));
			}
		}
	}
}

int main()
{
    
    	   
	cin>>n>>m>>s>>d;
	for(int i=0;i<n;i++) cin>>p[i];
	for(int i=0;i<m;i++)
	{
    
    
		cin>>a>>b>>len;
		g[a].push_back(node(b,len)); //无向图
		g[b].push_back(node(a,len));
	}
	dijk();
	cout<<num[d]<<" "<<ans[d]<<endl;
	print();
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45260385/article/details/110247432