PAT A1003 Emergency 题解
PAT A1003 Emergency
题目简述:
原题为英文题目,所以在这里简述一下题意:
给定n个点和m条无向路以及起点、终点
下面一行n个数,第i个数表示第i个点上的救援组数目(点权)
再往下m行每行三个整数,表示每一条路连接的两个端点以及花费(边权)
要求求出从起点到终点的最短路径数目以及最短路径上的最大救援组数目和
解题思路:
这道题和一般的最短路稍有不同:本题除了寻找最短路还要额外维护两个值——最短路数目和救援组数目和最大值
- 怎么处理呢?
增加两个维护类型,那我们也额外开两个数组记录呗:
一个数组记录最短路数目;一个数组记录完整的最短路路径,然后就可以根据路径来单独计算该条最短路径上的救援组数目,最后比较得出最大救援组数目和
- 怎么维护最短路径数目?
我们使用ans[i]来存储第i号节点的最短路径数目
在跑Dijkstra时,如果
dis[v]>dis[x]+e[i].val那么ans[v]=ans[x],因为不是最短路所以直接继承上一个节点的最短路数目即可如果
dis[v]==dis[x]+e[i].val那么ans[v]+=ans[x],因为最短路长度相等,所以累加最短路数目
- 怎么记录一条完整的最短路路径?
记录一条完整路径,那我们记录在路径上每一个点的前驱即可
需要特别注意的是:
因为在本题中点的前驱不一定只有一个,所以我们需要使用vector(也许有其他做法,这里不多赘述)
当更新了当前的最短路时,当前节点v的前驱应该先清空,然后再把前一个点x存入前驱
来讲讲原因:
因为存在多条最短路径,而每条最短路径经过的点是可能重复的(这里还不涉及到救援组数目最大值),所以记录点的前驱需要使用vector
如果最短路都更新了,那么前面存的前驱也就没有用了,所以需要清空
if(dis[v]>dis[x]+e[i].val) {
ans[v]=ans[x];
pre[v].clear();
pre[v].push_back(x);
dis[v]=dis[x]+e[i].val;
shan.push(make_pair(-dis[v],v));
}
else if(dis[v]==dis[x]+e[i].val) {
ans[v]+=ans[x];
pre[v].push_back(x);
}
- 记录了路径,那怎么维护救援组和的最大值?
我们在跑完Dijkstra部分后,进入dfs然后遍历vector来“复原”每一条最短路径
dfs中有两个参数:第一个now指当前的点,第二个sum表示至今的救援组数目和
如果now到达了起点,就用num比较出最大值
inline void dfs(int now,int sum) {
if(now==s) {
num=max(num,sum);
return ;
}
for(vector<int>::iterator it=pre[now].begin();it!=pre[now].end();it++) {
dfs(*it,sum+a[*it]);
}
}
完整Code:
解题思路如上所示,现在给出完整代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,m,s,u,v,w,t,tot,num,a[250010];
int dis[250010],vis[250010],head[250010],ans[250010];
vector<int> pre[250010];
priority_queue<pair<int,int> > shan;
struct node {
int to,net,val;
} e[250010];
inline void add(int u,int v,int w) {
e[++tot].val=w;
e[tot].to=v;
e[tot].net=head[u];
head[u]=tot;
}
inline void dijkstra(int s) {
fill(dis,dis+250010,20050206);
dis[s]=0;
ans[s]=1; //起点肯定有路径,所以初始值为1
shan.push(make_pair(0,s));
while(!shan.empty()) {
int x=shan.top().second;
shan.pop();
if(vis[x]) continue;
vis[x]=1;
for(register int i=head[x];i;i=e[i].net) {
int v=e[i].to;
if(dis[v]>dis[x]+e[i].val) { //更新最短路
ans[v]=ans[x];
pre[v].clear(); //一定要清空前驱,再压入x
pre[v].push_back(x);
dis[v]=dis[x]+e[i].val;
shan.push(make_pair(-dis[v],v)); //入队
}
else if(dis[v]==dis[x]+e[i].val) { //如果最短路长度相等
ans[v]+=ans[x]; //累加最短路数目
pre[v].push_back(x); //同样记录前驱
}
}
}
}
inline void dfs(int now,int sum) { //遍历所有最短路径求最大救援组数目和
if(now==s) { //回溯到起点,更新答案
num=max(num,sum);
return ;
}
for(vector<int>::iterator it=pre[now].begin();it!=pre[now].end();it++) { //利用vector不断遍历前驱
dfs(*it,sum+a[*it]);
}
}
int main() {
scanf("%d%d%d%d",&n,&m,&s,&t);
for(register int i=0;i<n;i++) {
scanf("%d",&a[i]);
}
for(register int i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dijkstra(s);
dfs(t,a[t]);
printf("%d %d",ans[t],num);
return 0;
}
最后,特别感谢一下RHL大佬对蒟蒻的指导qwq
PAT A1003 Emergency 题解的更多相关文章
- PAT甲题题解-1003. Emergency (25)-最短路径+路径数目
给出n个城市,m条边,起始点c1和目的点c2接下来给出n个城市的队伍数以及m条双向边问你求c1到c2的所有最短路径数目,以及其中经过的最多队伍数 先最短路dijkstra,同时建立vector数组pr ...
- 2019秋季PAT甲级_C++题解
2019 秋季 PAT (Advanced Level) C++题解 考试拿到了满分但受考场状态和知识水平所限可能方法不够简洁,此处保留记录,仍需多加学习.备考总结(笔记目录)在这里 7-1 Fore ...
- PAT 1003. Emergency (25)
1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emerg ...
- PAT 1003. Emergency (25) dij+增加点权数组和最短路径个数数组
1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emerg ...
- A1003. Emergency
As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...
- PAT 1003 Emergency
1003 Emergency (25 分) As an emergency rescue team leader of a city, you are given a special map of ...
- PAT甲题题解-1068. Find More Coins (30)-dp,01背包
一开始没多想,虽然注意到数据N<=10^4的范围,想PAT的应该不会超时吧,就理所当然地用dfs做了,结果最后一组真的超时了.剪枝啥的还是过不了,就意识到肯定不是用dfs做了.直到看到别人说用0 ...
- PAT甲题题解-1108. Finding Average (20)-字符串处理
求给出数的平均数,当然有些是不符合格式的,要输出该数不是合法的. 这里我写了函数来判断是否符合题目要求的数字,有点麻烦. #include <iostream> #include < ...
- PAT甲题题解-1128. N Queens Puzzle (20)-做了一个假的n皇后问题
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789810.html特别不喜欢那些随便转载别人的原创文章又不给 ...
随机推荐
- Java实现 蓝桥杯 算法训练 Balloons in a Box
试题 算法训练 Balloons in a Box 问题描述 你要写一个程序,使得能够模拟在长方体的盒子里放置球形的气球. 接下来是模拟的方案.假设你已知一个长方体的盒子和一个点集.每一个点代表一个可 ...
- Java实现 LeetCode 470 用 Rand7() 实现 Rand10()
470. 用 Rand7() 实现 Rand10() 已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数. 不要使用系 ...
- Java实现 LeetCode 376 摆动序列
376. 摆动序列 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5 ...
- Java实现 LeetCode 367 有效的完全平方数
367. 有效的完全平方数 给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False. 说明:不要使用任何内置的库函数,如 sqrt. 示例 1: ...
- Java实现 蓝桥杯VIP 算法训练 阿尔法乘积
蓝桥杯–阿尔法乘积 问题描述 计算一个整数的阿尔法乘积.对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身:否则的话,x的阿尔法乘积就等于它的各位非0的 ...
- Java实现 LeetCode 96 不同的二叉搜索树
96. 不同的二叉搜索树 给定一个整数 n,求以 1 - n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 ...
- java实现第六届蓝桥杯饮料换购
饮料换购 饮料换购 乐羊羊饮料厂正在举办一次促销优惠活动.乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去,但不允许赊账. 请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么, ...
- js数据劫持 Object.defineProperty() 作用
原生js Object.defineProperty() 作用 假设我们有一个obj对象,我们要给他设置一个name属性会这么做 Object.defineProperty()也可以设置对象属性 这个 ...
- 编译e2fsprogs-1.40.2
1.解压源码 tar zxvf e2fsprogs-1.40.2.tar.gz 2.配置 ./configure --enable-elf-shlibs --host=arm-linux --with ...
- mysql中的四种常用的引擎
MySQL常用的引擎有:InnoDB存储引擎.MyISAM存储引擎.MEMORY存储引擎.Archive存储引擎 InnoDB存储引擎 InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID) ...