Inter-city emergency rescue (25 points) (Dijkstra)

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

Question ideas:
1. The essence of the question is to find the shortest path. By the way, some operations have been carried out in the process of finding the shortest path.
2. The number of the shortest path num[MAXN] array to achieve
3. The maximum value of "point weight", use the array weight[], w[] array to achieve
4. Print the shortest path, record the previous one of each vertex on the path point. Recursive printing is used in the final printing.
5. The above three concepts are described in more detail in the code comments. This is a relatively simple method. This question itself requires a lot of information. If you still don’t understand, you can comment on the private message and I will reply in time.

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 505;
const int INF = 0x3f3f3f3f;
int Graph[MAXN][MAXN];	//图
int weight[MAXN];		//成熟u中的物资数目
int d[MAXN];			//起点s到达顶点u的最短距离
int w[MAXN] = {
    
     0 };	//起点s到达顶点u收集的最大物资数
int num[MAXN] = {
    
     0 };	//起点s到达顶点u的最短轮径的条数
int pre[MAXN];			//起点s到达顶点v的最短路径的前一个顶点
bool Visited[MAXN] = {
    
     false };
int n, m, s, ter;
void Dijkstra(int s);
void DFS(int s, int v);	//递归遍历,如果不懂这个递归,要好好考虑一下,因为类似的递归还有很多
int main()
{
    
    
	cin >> n >> m >> s >> ter;		//ter是终点
	fill(Graph[0], Graph[0] + MAXN * MAXN, INF);
	for (int i = 0; i < n; i++)
	{
    
    
		cin >> weight[i];		//输入每个顶点的人员数
		pre[i] = i;		//初始化为每个顶点的前一个顶点为本身
	}
	int a, b, c;
	while (m--)
	{
    
    
		cin >> a >> b >> c;
		Graph[a][b] = Graph[b][a] = c;	//建立无向图
	}

	Dijkstra(s);

	cout << num[ter] << " " << w[ter] << endl;	//这里为什么下标为ter,回过头看一下这些数组本身的含义是什么意思
	DFS(s, ter);
	return 0;
}
void Dijkstra(int s)
{
    
    
	fill(d, d + MAXN, INF);
	d[s] = 0;						
	w[0] = weight[0];
	num[s] = 1;			//以上是初始化
	for (int i = 0; i < n; i++)		//找到未访问顶点中d[]最小的
	{
    
    
		int u = -1, MIN = INF;
		for (int j = 0; j < n; j++)
			if (!Visited[j] && d[j] < MIN)
			{
    
    
				u = j;
				MIN = d[j];
			}

		if (u == -1) return;
		Visited[u] = true;	
		for (int v = 0; v < n; v++)	//以u作为中介点查下下一个顶点v的性质
		{
    
    
			if (!Visited[v] && Graph[u][v] != INF)
			{
    
    
				if (d[u] + Graph[u][v] < d[v])
				{
    
    
					d[v] = d[u] + Graph[u][v];	//更新起点到v顶点的最短路径长度
					w[v] = w[u] + weight[v];	//更新人数
					num[v] = num[u];			//s到v与s到u的最短路径个数相同
					pre[v] = u;					//v的上一个顶点是u
				}
				else if (d[u] + Graph[u][v] == d[v])
				{
    
    
					num[v] += num[u];			//到达v的最短路径的条数加上到达u的最短路径的条数
					if (w[u] + weight[v] > w[v])	//在路径当都不变时,如果人数增多那么就更新人数
					{
    
    
						w[v] = w[u] + weight[v];
						pre[v] = u;
					}

				}
			}
		}
	}
}
void DFS(int s, int v)	//从终点开始向上找,和并查集的感觉有点像
{
    
    
	if (v == s)		//如果当前顶点是起点,那么就停止递归
	{
    
    
		cout << v;
		return;
	}

	DFS(s, pre[v]);
	cout << " " << v;
}

Guess you like

Origin blog.csdn.net/xdg15294969271/article/details/114320793