1003 Emergency (25分)/Dijkstra

题目链接

分析

常规的Dijkstra求解最短路径的题,只不过添加了“第二标尺”——点权,并要求输出不同最短路径的数目。解题方法参见我的另一个博文:最短路径之Dijkstra算法

AC代码

#include<iostream>
#include<algorithm>
using namespace std;
const int maxv = 500;
const int inf = 1000000000;
int n, G[maxv][maxv], weight[maxv], w[maxv], d[maxv], num[maxv];
bool vis[maxv];
void Dijkstra(int s) {
	/*初始化*/
	fill(d, d + maxv, inf);
	d[s] = 0; w[s] = weight[s]; num[s] = 1; //注意w和num的初始化方式
	for (int i = 0; i < n; i++) {
		int u = -1, MIN = inf;
		for (int j = 0; j < n; j++) {
			if (vis[j] == false && d[j] < MIN) {
				u = j; MIN = d[j];
			}
		}
		if (u == -1) return;
		vis[u] = true; //当心漏掉
		for (int v = 0; v < n; v++) {
			if (vis[v] == false && G[u][v] != inf) {
				if (d[u] + G[u][v] < d[v]) {
					d[v] = d[u] + G[u][v];
					w[v] = weight[v] + w[u];
					num[v] = num[u];
				}
				else if (d[u] + G[u][v] == d[v]) {
					num[v] += num[u]; //与点权无关
					if (weight[v] + w[u] > w[v]) w[v] = weight[v] + w[u];
				}
			}
		}
	}
}
int main() {
	int m, s, v;
	cin >> n >> m >> s >> v;
	for (int i = 0; i < n; i++) {
		scanf("%d", &weight[i]);
	}
	fill(G[0], G[0] + maxv * maxv, inf); 
	//注意初始化G为inf,G为二维数组,G[0]表示首元素地址步长为sizeof(int)
	while (m--) {
		int c1, c2, len;
		scanf("%d%d%d", &c1, &c2, &len);
		G[c1][c2] = G[c2][c1] = len; //两个顶点之间距离
	}
	Dijkstra(s);
	cout << num[v] <<" "<< w[v];
	return 0;
}
发布了30 篇原创文章 · 获赞 5 · 访问量 1040

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104094046
今日推荐