作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60
0 1 3
dijkstra模板
注释部分为本题所需 看情况使用
#define INF 0x3f3f3f3f
#define rep(i, l, r) for(int i = l; i < r; i++)
const int MAXN = 1e5 +7;
int N, M; //N点M边
int vis[MAXN]; //标记是否加入
int dis[MAXN]; //记录i点和源点距离
int num[MAXN]; //记录源点到i点最短路条数
int G[MAXN][MAXN] //记录边图
int P[MAXN] //记录前驱
/*
int ret[MAXN] //记录每点的物品数
int gather[MAXN] //记录到i点的最短路上的最多物品数
*/
void dijstra(int s){
fill(vis, vis + MAXN, 0);
fill(P, P + MAXN, -1);
fill(num, num, 0);
fill(dis, dis + MAXN, INF);
/*
fill(gather, gather + MAXN, 0);
*/
rep(i, 0, N) {
int u = -1, min = INF;
rep(j, 0, N)
if(!vis[j] && dis[j] < min) {
min = dis[j];
u = j;
}
if(u == -1) return;
vis[u] = 1;
rep(v, 0, N) {
if(!vis[v] && G[u][v] != INF) {
if(dis[v] > dis[u] + G[u][v]){ //v由u点到达更短
P[v] = u; //记录前驱
dis[v] = dis[u] + G[u][v]; //修改最短路长度
num[v] = num[u]; //到v的最短路经过u 条数也就和u一致
/*
gather[v] = gather[u] + ret[v];
*/
}
else if(dis[v] == dis[u] + G[u][v]){
num[v] += num[u]; //相等时有多条路径可达 条数累加
/*
因为在 ‘城市救援 ’一题中还要求救援人数最多
if(gather[v] < gather[u] + ret[v]){
P[v] = u;
gather[v] = gather[u] + ret[v];
}
*/
}
}
}
}
}
AC代码
#include<bits/stdc++.h>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define lINF (1ll << 60)
#define eps 1e-8
#define pi acos(-1.0)
#define e exp(1.0)
#define ios ios::sync_with_stdio(false)
#define rep(i,l,r) for(int i=l;i<r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
using namespace std;
const int MAXN = 505;
const int mod = 109;
template<class T>inline void read(T &res){
char c;T flag = 1;
while((c = getchar()) < '0' || c > '9')if(c == '-')flag = -1;res = c - '0';
while((c = getchar()) >= '0' && c <= '9')res = res * 10 + c - '0'; res *= flag;
}
template<class T>inline void write(T x){
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x/10);
putchar(x % 10 + '0');
}
ll MyPow(ll a, ll b){ ll sum = 1;while (b) {if (b & 1) {sum = (sum * a) % mod;b--;}b /= 2;a = a * a % mod;}return sum;}
ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); }
ll isprime(ll n){if(n <= 1) return 0;if(n == 2) return 1;rep(i, 2, sqrt(n) + 1) if(n % i == 0) return 0;return 1;}
int num[MAXN], G[MAXN][MAXN], vis[MAXN], dis[MAXN], gather[MAXN];
int res[MAXN], P[MAXN], node[MAXN];
int N, M, S, D;
int x, y, z;
void dijkstra (int s) {
fill(P, P + MAXN, -1);
fill(num, num + MAXN, 0);
fill(vis, vis + MAXN, 0);
fill(dis, dis + MAXN, INF);
fill(gather, gather + MAXN, 0);
dis[s] = 0;
num[s] = 1;
P[s] = 0;
gather[s] = res[s];
rep(i, 0, N) {
int u = -1, min = INF;
rep(j, 0, N) {
if(!vis[j] && dis[j] < min) {
min = dis[j];
u = j;
}
}
if(u == -1) return ;
vis[u] = 1;
rep(v, 0, N) {
if(!vis[v] && G[u][v] != INF) {
if(dis[v] > dis[u] + G[u][v]) {
P[v] = u;
num[v] = num[u];
dis[v] = dis[u] + G[u][v];
gather[v] = gather[u] + res[v];
}
else if(dis[v] == dis[u] + G[u][v]) {
num[v] += num[u];
if(gather[v] < gather[u] + res[v]) {
P[v] = u;
gather[v] = gather[u] + res[v];
}
}
}
}
}
}
int main() {
cin >> N >> M >> S >> D;
fill(G[0], G[0] + MAXN * MAXN, INF);
rep(i, 0, N) cin >> res[i];
rep(i, 0, M) {
cin >> x >> y >> z;
G[x][y] = G[y][x] = z;
}
dijkstra(S);
cout << num[D] << " " << gather[D] << endl;
int o = 0;
node[o++] = D;
while(P[D] != 0) {
node[o++] = P[D];
D = P[D];
}
node[o] = S;
per(i, o, 0){
if(i) cout << node[i] << " ";
else cout << node[i] << endl;
}
return 0;
}

本文介绍了一个城市应急救援队伍负责人如何利用特殊地图,规划从出发城市到目的地城市的最短路径,并沿途召集最多的救援队。通过输入城市数量、快速道路信息及救援队分布,采用Dijkstra算法实现路径规划。
271

被折叠的 条评论
为什么被折叠?



