团体程序设计天梯赛 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;
}