天梯赛 L2-001 紧急救援 (25 分)
单元最短路+最短路数量+最大点权和+输出路径
L2-001 紧急救援 (25 分)
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出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
本题属于单元最短路径的拓展应用问题,在求最短路的同时,要求记录最短路的数量以及 最大点权和 还有 输出最短路径。
①最短路数量:用一个cnt数组来维护,从起点开始最短路数量初始设置为1,如果到t的最短路唯一,cnt[j] = cnt[t] 到j的最短路数量也就是到t的最短路数量。 否则 要 加上 到 t的最短路数量 之和。
②最大点权和,同理 更新最短路径的同时更新点权和。
③ 记录路径,用pre数组,反向去找,如果确定了此时最短路是从t过来来的 那么 pre[j] = t 表示 j这个点 是从t 走过来的。
#include<bits/stdc++.h>
#include<queue>
using namespace std;const int N =510;int n,m,S,T;
int w[N];
int d[N][N];
bool st[N];
int dist[N];
int cnt[N],sum[N]; // 最短路径数量 最大点权和
int pre[N]; // 输出路径 void dijkstra()
{memset(dist,0x3f,sizeof dist);dist[S] = 0; cnt[S] = 1; sum[S] = w[S];for(int i=0;i<n;i++){int t= -1;for(int j=0;j<n;j++)if(!st[j] && (t==-1 || dist[t] > dist[j]))t = j;st[t] = true;for(int j=0;j<n;j++){if(dist[j] > dist[t] + d[t][j]) // 最短路是唯一的 {dist[j] = dist[t] + d[t][j];cnt[j] = cnt[t];sum[j] = sum[t] +w[j]; pre[j] = t;}else if( dist[j] == dist[t] + d[t][j]) //最短路是不唯一的 {cnt[j] +=cnt[t];if(sum[j] < sum[t] + w[j]){sum[j] = sum[t] + w[j];pre[j] = t;}} } }
}int main()
{ memset(d,0x3f,sizeof d);cin>>n>>m>>S>>T;for(int i=0;i<n;i++) cin>>w[i];while(m--){int a,b,c;cin>>a>>b>>c;d[a][b] = d[b][a] = min(d[a][b],c);} dijkstra();cout<<cnt[T] << " " << sum[T] << endl;vector<int> path;for(int i= T; i!= S; i = pre[i]) path.push_back(i);cout<<S;for(int i = path.size()-1; i>=0; i--) cout<<" "<<path[i];
}
天梯赛 L2-001 紧急救援 (25 分)相关推荐
- 天梯赛:L2-001 紧急救援 (25 分)
题目详情 - L2-001 紧急救援 (25 分) (pintia.cn) 题解:使用dijkstra算法就可以了,难点在于如何存储路径.我首先十分单纯的用了pair<int,int>进行 ...
- 天梯赛 L2-030 冰岛人 (25 分)
天梯赛 L2-030 冰岛人 (25 分) 思路分析 看见这种题目,建议直接放弃... 仅打卡使用,本人不会做= = 参考代码 #include <iostream> #include & ...
- 2020团队程序设计天梯赛 L2-2 口罩发放 (25分)
2020团队程序设计天梯赛 赛后听许多人感慨,火锅火锅吃不掉,彩票彩票刮不开,调和平均也调不和,而像我这种口罩发不下去的人也在大多数吧 L2-2 口罩发放 (25分) 为了抗击来势汹汹的 COVID1 ...
- C++学习之路 | PTA(天梯赛)—— L2-024 部落 (25分)(带注释)(并查集)(精简)
L2-024 部落 (25分) 在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈.我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部 ...
- 天梯赛 L2-032 彩虹瓶 (25 分)
L2-032 彩虹瓶 (25 分) 思路: 读完题目就知道是用栈处理, 值得注意的是 1 while (s.size() && s.top() == d)中,要先判断栈的大小,再判断栈 ...
- 天梯赛 L2-030 冰岛人 (25 分) map
L2-030 冰岛人 (25 分) 2018年世界杯,冰岛队因1:1平了强大的阿根廷队而一战成名.好事者发现冰岛人的名字后面似乎都有个"松"(son),于是有网友科普如下: 冰岛人 ...
- 天梯赛 L2-021 点赞狂魔 (25 分)
题目链接 思路 这道题在L2里属于偏简单的一道,数据范围很友好,倾向于使用逻辑而非算法.但想要比较轻松的完成这道题目还是需要一些stl使用经验的. 对于一个用户,有几个需要记录的属性: 姓名,用于输出 ...
- 天梯赛模拟 链表去重 (25 分)
题目: 给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉.即对每个键值 K,只有第一个绝对值等于 K 的结点被保留.同时,所有被删除的结点须被保存在另一个链表上.例如给定 L 为 2 ...
- 团体程序设计天梯赛-L2组
团体程序设计天梯赛-L2组 -------------------------------------------------------------------------------- 题目传送门 ...
最新文章
- OC基本数据存储方式
- 2021科大讯飞-车辆贷款违约预测赛事 Top1方案!
- python 多态 协议详解
- swift3.0 渐变色
- 添加全局函数$.extend和对象方法$.fn
- 【一周入门MySQL—3】多表查询、子查询、常用函数
- LiveVideoStackCon讲师热身分享 ( 十一 ) —— 短视频APP的架构设计
- 慎用window.showModalDialog()
- 进程调度 操作系统第二章知识点归纳总结
- python 连接MS sql server2005数据库
- Tomcat最大线程数的设置
- ESP32-C3入门教程 WiFi篇⑥——基于串口的 WiFi 智能配网
- IE浏览器设置UserAgent
- mplayer播放器管道重构版
- 用Squid和DNSPod打造自己的CDN详细教程
- draw.io和plantuml替代visio画图工具
- 一起谈.NET技术,.NET十年(下)
- MATLAB用fwind2函数设计近似圆对称二维带通滤波器
- Cesium开发:关于加载CGCS2000切片
- 火影忍者OL手游怎么在电脑上玩 火影忍者OL安卓模拟器玩法教程