Rescate de emergencia entre ciudades (25 puntos) (Dijkstra)

Como jefe del equipo de rescate de emergencia de una ciudad, tiene un mapa especial del país. En el mapa, hay varias ciudades dispersas y algunas carreteras rápidas que conectan las ciudades. El número de equipos de rescate en cada ciudad y la longitud de cada autopista que conecta las dos ciudades están marcados en el mapa. Cuando otras ciudades tienen llamadas de emergencia, su tarea es llevar a su equipo de rescate lo antes posible al lugar donde ocurrió el incidente y, al mismo tiempo, reunir tantos equipos de rescate como sea posible en el camino.

Formato de entrada:
ingrese la primera línea para obtener 4 números enteros positivos N, M, S, D, donde N (2≤N≤500) es el número de ciudades. Por cierto, suponga que el número de la ciudad es 0 ~ ( N − 1); M es el número de autopistas; S es el número de ciudad del lugar de salida; D es el número de ciudad del destino.

La segunda línea da N números enteros positivos, donde el i-ésimo número es el número de equipos de rescate en la i-ésima ciudad, y los números están separados por espacios. En las siguientes líneas M, cada línea proporciona información sobre una vía rápida, a saber: ciudad 1, ciudad 2 y la longitud de la vía rápida, separadas por espacios, y los números son todos enteros y no exceden de 500. La entrada asegura que el rescate sea factible y que la solución óptima sea única.

Formato de salida: la
primera línea muestra el número de caminos más cortos y el número máximo de equipos de rescate que se pueden reunir. La segunda línea da como resultado el número de la ciudad que pasó en el camino de S a D. Los números están separados por espacios y no debe haber espacios adicionales al final de la salida.
Muestra de entrada:

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

Salida de muestra:

2 60
0 1 3

Ideas de preguntas:
1. La esencia de la pregunta es encontrar el camino más corto Por cierto, se han realizado algunas operaciones en el proceso de encontrar el camino más corto.
2. El número de la matriz num [MAXN] de ruta más corta para lograr
3. El valor máximo de "peso de punto", use la matriz de peso [], w [] para lograr
4. Imprima la ruta más corta, registre la anterior de cada vértice en el punto de ruta. La impresión recursiva se utiliza en la impresión final.
5. Los tres conceptos anteriores se describen con más detalle en los comentarios del código. Este es un método relativamente simple. Esta pregunta en sí misma requiere mucha información. Si aún no lo entiende, puede comentar el mensaje privado y le responderé a tiempo.

#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;
}

Supongo que te gusta

Origin blog.csdn.net/xdg15294969271/article/details/114320793
Recomendado
Clasificación