团体程序设计天梯赛 L2-001 紧急救援 (25分)(最短路径)

题目链接:

L2-001 紧急救援 (25分)

思路:

使用dijkstra算法来求最短路,其中记录最短路条数、以及每个点所能聚集到的最大人数;

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 505;
const int INF = 1 << 30;
struct edge { int to, cost; };
typedef pair<int, int> P;     //distance & no
int n, m, from, to;
vector<edge> G[maxn];
int d[maxn], resc[maxn], rcd[maxn], num[maxn], fa[maxn];
#define UPDATE { rcd[e.to] = resc[e.to] + rcd[v]; fa[e.to] = v; que.push(P(d[e.to], e.to)); } //update [ rcd & fa & que.push ]
void dijkstra(int s) {
	fill(d, d + n, INF);
	for(int i = 0; i < n; i++) fa[i] = i;
	d[s] = 0, rcd[s] = resc[s], num[s] = 1;
	priority_queue<P, vector<P>, greater<P> > que;
	que.push(P(0, s));
	while(!que.empty()) {
		P p = que.top(); que.pop();	
		int v = p.second;
		if(d[v] < p.first) continue;
		for(edge & e : G[v]) {
			if(d[e.to] > d[v] + e.cost) {
				d[e.to] = d[v] + e.cost;
				num[e.to] = num[v];
				UPDATE;
			}else if(d[e.to] == d[v] + e.cost) {
				if(fa[e.to] != v) num[e.to] += num[v];
				if(rcd[e.to] < rcd[v] + resc[e.to]) UPDATE;
			}
		}
	}
}
void printPath(int d) {
	if(d == fa[d]) { printf("%d", d); return; }
	printPath(fa[d]);
	printf(" %d", d);
}
int main() {
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif
	scanf("%d %d %d %d", &n, &m, &from, &to);
	for(int i = 0; i < n; i++) scanf("%d", resc + i);
	while(m--){
		int x, y, c;
		scanf("%d %d %d", &x, &y, &c);
		G[x].push_back(edge{y, c});
		G[y].push_back(edge{x, c});	
	}
	dijkstra(from);
	printf("%d %d\n", num[to], rcd[to]);
	printPath(to);
	return 0;
}
posted @ 2020-01-14 17:41  YuhanのBlog  阅读(137)  评论(0编辑  收藏  举报