【1003 25 最短路径数量 最大点权】 Emergency

传送门

题意

给定 \(n\) 个点,\(m\) 条边的无向图,起点 \(c_1\) ,终点 \(c_2\)\(n\) 个点权,\(m\) 条边的边权, 求从 \(c_1\)\(c_2\) 的最短路径的条数及所有最短路径中的最大点权和

数据范围

\(1\leq n\leq 500\)

题解

  • 额外维护从起点到每个点的最短路径个数 pathnum,从起点到每个点的最短路径上的最大点权和 cnt
  • dijkstra 变形,在用当前路径最短的点进行更新时进行如下判断
    • 如果更新距离,最短路径个数替换为新的最短路径个数,点权加上当前点
    • 如果距离相等,终点累加起点的最短路径条数,点权取最大值

Code

#include <bits/stdc++.h>
using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int p[N], d[N];
int n, m, c1, c2;
int cnt[N], pathcnt[N];
bool st[N];
struct edge {
	int to, cost;
	edge(int t, int c) : to(t), cost(c) {}
};

vector<vector<edge>> g(N);
using arr = array<int, 2>;
void dijkstra() {
	memset(d, 0x3f, sizeof d);
	priority_queue<arr, vector<arr>, greater<arr>> que;
	d[c1] = 0;
	pathcnt[c1] = 1;
	cnt[c1] = p[c1];
	que.push({0, c1});

	while (!que.empty()) {
		auto t = que.top(); que.pop();
		for (auto& e : g[t[1]]) {
			if (d[e.to] > t[0] + e.cost) {
				d[e.to] = t[0] + e.cost;
				que.push({d[e.to], e.to});
				pathcnt[e.to] = pathcnt[t[1]];
				cnt[e.to] = cnt[t[1]] + p[e.to];
			} else if (d[e.to] == t[0] + e.cost) {
				pathcnt[e.to] += pathcnt[t[1]];
				cnt[e.to] = max(cnt[t[1]] + p[e.to], cnt[e.to]);
			}

		}
	}

}

int main() {
	cin >> n >> m >> c1 >> c2;

	for (int i = 0; i < n; i++) {
		cin >> p[i];
	}

	while (m--) {
		int u, v, w; cin >> u >> v >> w;
		g[u].push_back(edge(v, w));
		g[v].push_back(edge(u, w));
	}

	dijkstra();

	cout << pathcnt[c2] << ' ' << cnt[c2];

}
posted @ 2021-01-20 05:09  Hyx'  阅读(35)  评论(0)    收藏  举报