Applications of Dijkstra's Algorithm

1. Problem description

poor travel? "Poor" travel?
Time Limit: 1000 MS Memory Limit: 10000 KB

Description

Poor little A has a dream, that is, to take a poor trip to country t, but the reality is cruel. There are a total of n (n<=500) in the world where A is located
There are a total of E (E<=50000) roads connecting countries, and the i-th country charges Bi to foreigners entering it.
, and little A’s family lives in country s, he must use these roads to transit between countries and finally reach country t (unless he is lucky enough
You can go directly from country s to country t). But the poor little A only has M (M<=100) yuan, so he must plan carefully for the trip.
At the same time, little A is really yearning for country t, so he hopes to take the shortest way to reach country t as soon as possible. This problem stumps little
A, now he asks you to help him calculate how long the shortest path he takes to reach country t is.

Input

Input T (T<=10) in the first line means that there are T sets of data. Enter n, E, s, t, M in the first line of each set of data, respectively indicating the world where little A is located
The number of countries, the total number of roads between countries, the nationality of little A, the country that little A yearns for, and the family background of little A; the next line enters n positive
The integer Bi represents the toll charged by the i-th country (since little A is a native of country s, country s will not collect it, but country t will do so);
Enter three positive integers u(1<=u<=n), v(1<=v<=n), and w in each line of E line, which means that there is an infinite network of length w between country u and country v.
to the edge (possibly with multiple edges). The input guarantees that the final result will not overflow the int.

Output

Output T lines of positive integers, and the i-th line represents the shortest path for the i-th group of data A to reach the country t without spending more than M yuan. If little A cannot reach country t, lose
out -1.

Sample Input

3
2 2 1 2 10
20 10
1 2 1
1 2 2
3 1 1 3 10
1 1 1
2 3 1
3 3 1 3 10
1 11 1
1 2 1
1 2 3
2 3 1

Sample Output

1
-1
-1

2. Algorithm analysis

In this question, the purpose is to find the shortest path from country S to country T. Obviously, Dijkstra's algorithm should be used. The corresponding charge can be regarded as the weight of edge to edge, and the final cost is the weight sum of the shortest path. If it is less than M, then Little A can reach, if it is greater than M, then Little A cannot reach

#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;

// 结构体表示图中的一条边
struct country {
	int v, w; // 顶点和权重
};

vector <country> world[505]; // 图的邻接表表示

// 结构体表示图中的一个顶点
struct vertex {
	int m, dis, v; // m: 剩余的金钱,dis: 距离,v: 顶点
};

// 自定义比较函数,用于优先队列的排序
struct mycompare {
	bool operator()(vertex a, vertex b) {
		return a.dis > b.dis; // 根据距离比较顶点
	}
};

priority_queue<vertex, vector<vertex>, mycompare> arr; // 用于Dijkstra算法的优先队列

int main() {
	int T, n, E, s, t, M, x, y, z;
	cin >> T; // 读取测试用例的数量

	int cost[505]; // 数组用于存储每个顶点的成本
	int distance[505][105]; // 二维数组用于存储最短距离
	bool flag[505][105]; // 二维数组用于跟踪访问过的顶点

	while (T--) { // 遍历每个测试用例
		memset(distance, -1, sizeof(distance)); // 将距离数组初始化为-1
		memset(flag, true, sizeof(flag)); // 将标记数组初始化为true

		cin >> n >> E >> s >> t >> M; // 读取顶点数、边数、起点、终点和初始金钱

		for (int i = 1; i <= n; i++)
			cin >> cost[i]; // 读取每个顶点的成本

		for (int i = 0; i < E; i++) {
			cin >> x >> y >> z; // 读取边的起点、终点和权重
			country temp;
			temp.v = y;
			temp.w = z;
			world[x].push_back(temp); // 将边添加到起点的邻接表中
			temp.v = x;
			world[y].push_back(temp); // 将边添加到终点的邻接表中(无向图)
		}

		vertex temp;
		temp.m = M; temp.dis = 0; temp.v = s; distance[temp.v][M] = 0;
		arr.push(temp); // 将起点加入优先队列

		while (!arr.empty()) {
			temp = arr.top(); // 取出距离最小的顶点
			arr.pop();

			int p = temp.v;
			if (!flag[p][temp.m] || temp.dis > distance[temp.v][temp.m]) continue; // 如果顶点已被访问过或距离更大,则跳过此次循环

			flag[p][temp.m] = false; // 标记顶点为已访问

			for (int i = 0; i < world[p].size(); i++) {
				int v = world[p][i].v;
				if (v == s) continue; // 如果顶点为起点,则跳过此次循环

				if (temp.m >= cost[v] && (distance[v][temp.m - cost[v]] == -1 || temp.dis + world[p][i].w < distance[v][temp.m - cost[v]])) {
					distance[v][temp.m - cost[v]] = temp.dis + world[p][i].w; // 更新距离数组

					vertex point;
					point.dis = temp.dis + world[p][i].w;
					point.m = temp.m - cost[v];
					point.v = v;
					arr.push(point); // 将新的顶点加入优先队列
				}
			}
		}

		int ans = 1000000;
		bool index = 0;

		for (int i = 0; i <= M; i++) {
			if (distance[t][i] != -1) {
				ans = min(ans, distance[t][i]); // 更新最短距离
				index = 1;
			}
		}

		if (!index)
			cout << -1 << endl;
		else
			cout << ans << endl;

		for (int i = 1; i <= n; i++)
			world[i].clear(); // 清空邻接表
	}
}

Guess you like

Origin blog.csdn.net/lyhizjj/article/details/130749526