【图论-最短路】【P3393】逃离僵尸岛
Description
小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家。
该国有N个城市,城市之间有道路相连。一共有M条双向道路。保证没有自环和重边。
K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入。由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市。换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险。
小a住在1号城市,国际空港在N号城市,这两座城市没有被侵略。小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所以晚上要住旅店。安全的的城市旅馆比较便宜要P元,而被危险的城市,旅馆要进行安保措施,所以会变贵,为Q元。所有危险的城市的住宿价格一样,安全的城市也是。在1号城市和N城市,不需要住店。
小a比较抠门,所以他希望知道从1号城市到N号城市所需要的最小花费。
输入数据保证存在路径,可以成功逃离。输入数据保证他可以逃离成功。
Input
第一行4个整数(N,M,K,S)
第二行2个整数(P,Q)
接下来K行,ci,表示僵尸侵占的城市
接下来M行,ai,bi,表示一条无向边
Output
一个整数表示最低花费
Sample Input
Sample Output
Hint
对于100%数据,2 ≦ N ≦ 100000, 1 ≦ M ≦ 200000, 0 ≦ K ≦ N - 2, 0 ≦ S ≦ 100000
1 ≦ P < Q ≦ 100000
Solution
思路十分清晰:先求出所有是危险区域的点,然后跑一遍spfa。
以下为了叙述方便,记被占领的点为黑色的点,危险的点为灰色的点,安全的点为白色的点。
但是怎么求灰色的点呢?暴力的方法当然是直接枚举所有黑色的点,各跑一遍spfa。然后存下来,但是一共最多有n(同阶)个点,spfa最多要n(同阶)层……然后你就炸了
考虑我们在这一遍spfa的时候并不需要清楚的知道它离我们规定的起点的距离。只需要知道它离距离他最近的点的距离即可。所以我们可以一次性把所有的黑色点压到队列里面一起spfa。这样我们的frog数组确切的含义就是距离他最近的黑色点离他的距离。
然后我们使用数组记录那些点是灰色的,然后跑一边真正的spfa。
几个坑点:1、long long
2、黑色点不能走
3、最后一个点和第一个点不需要算点权。
4、由于我们每条路走过去都可能由两个花费,所以不能在spfa第一次搜到目标点的时候直接输出exit(0).(这点好像很基础但我太久没写忘了)
Code
#include<queue>
#include<cstdio>
#include<cstring>
#define int long long
#define maxn 100010
#define maxm 400010 inline void qr(int &x) {
char ch=getchar();int f=;
while(ch>''||ch<'') {
if(ch=='-') f=-;
ch=getchar();
}
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
x*=f;
return;
} inline int max(const int &a,const int &b) {if(a>b) return a;else return b;}
inline int min(const int &a,const int &b) {if(a<b) return a;else return b;}
inline int abs(const int &x) {if(x>) return x;else return -x;} inline void swap(int &a,int &b) {
int c=a;a=b;b=c;return;
} int n,m,k,s,p,q; const long long INF = (1ll<<); struct Edge {
int to,nxt;
};
Edge edge[maxm];int hd[maxn],ecnt;
inline void cont(const int &from,const int&to) {
edge[++ecnt].to=to;
edge[ecnt].nxt=hd[from];
hd[from]=ecnt;
} int a,b,c[maxn],frog[maxn],ans=;
bool dangerous[maxn],cant[maxn];
std::queue<int>Q; void jiadespfa() { //拼音大法好
for(int i=;i<=n;++i) frog[i]=INF;
for(int i=;i<=k;++i) {frog[c[i]]=;Q.push(c[i]);cant[c[i]]=true;}
while(!Q.empty()) {
int h=Q.front();Q.pop();
for(int i=hd[h];i;i=edge[i].nxt) {
int &to=edge[i].to;
if(frog[to]>frog[h]+) {
frog[to]=frog[h]+;if(frog[to]<=s) {
dangerous[to]=true;Q.push(to);
}
}
}
}
} void zhendespfa() { //拼音大法好
for(int i=;i<=n;++i) frog[i]=INF;
frog[]=;Q.push();
while(!Q.empty()) {
int h=Q.front();Q.pop();
for(int i=hd[h];i;i=edge[i].nxt) {
int &to=edge[i].to;int v=(dangerous[to]?q:p);
if(cant[to]) continue;
if(to==n) {
ans=min(ans,frog[h]);
continue;
}
if(frog[to]>frog[h]+v) {
frog[to]=frog[h]+v;Q.push(to);
}
}
}
} main() {
qr(n);qr(m);qr(k);qr(s);qr(p);qr(q);
for(int i=;i<=k;++i) qr(c[i]);
for(int i=;i<=m;++i) {
a=b=;qr(a);qr(b);cont(a,b);cont(b,a);
}
jiadespfa();
zhendespfa();
printf("%lld\n",ans);
return ;
}
Summary
1、在不需要确切知道当前点和目标点的距离,而是需要知道每个点和给定的一些点的最近距离时,可以把给定的点全部压到队列里面,一起spfa。
2、spfa不能搜到就输出(这不是废话吗……要不然直接bfs不就成了)
【图论-最短路】【P3393】逃离僵尸岛的更多相关文章
- P3393 逃离僵尸岛
P3393 逃离僵尸岛 啊.好久不写dij手都生了 这道题就是预先处理出是否是危险城市,然后跑一个最短路就行了 然后因为我感觉这个对时间要求不大紧.判断危险城市时就写了个电风扇(DFS) 然后T飞了呜 ...
- luogu P3393 逃离僵尸岛-搜索剪枝+spfa
P3393 逃离僵尸岛 题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被 ...
- luogu P3393 逃离僵尸岛
luoguP3393逃离_僵尸岛_ 一道洛谷不知道哪门子月赛的题 可以用此题来练习最短路算法 SPFA和dijkstra的练习题(关于Floyed,他死了 思路: 本题是最短路板子. 首先就是建立虚点 ...
- 洛谷⑨月月赛Round2 P3393逃离僵尸岛[最短路]
题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入 ...
- Luogu P3393 逃离僵尸岛【最短路】By cellur925
题目传送门 题目大意:(其实概括出来也就基本做完了hh)在一张有$n$个点,$m$条边的无向图上,有$k$个点是不能经过的,而与之距离不超过$s$的点,到他们会花费$Q$元,到其他点会花费$p$元,求 ...
- 洛谷P3393逃离僵尸岛 最短路
貌似一直不写题解不太好QAQ 但是找不到题啊... 随便写点水题来补博客吧 题目不pa了,点链接吧... 点我看题 很明显这是道sb题... 思路: 对于每一个僵尸城市预处理其 s 距离内的城市,然 ...
- 洛谷P3393 逃离僵尸岛
题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入 ...
- 【luogu P3393 逃离僵尸岛】 题解
题目链接:https://www.luogu.org/problemnew/show/P3393 被占领的点可以先连在一个点上然后只需要对这一个点bfs一遍就可以求所有的危险点 #include &l ...
- 洛谷 P3393 逃离僵尸岛
洛谷 这道题目其实是最短路裸题. 首先看到题目,要求的到"被占点"距离不大于S的点,自然想到了以"被占点"为源点,求一遍最短路,处理出"危险点&quo ...
- [题解] 洛谷 P3393 逃离僵尸岛
题目TP门 很明显是一个最短路,但是如何建图才是关键. 对于每一个不可遍历到的点,可以向外扩散,找到危险城市. 若是对于每一个这样的城市进行搜索,时间复杂度就为\(O(n^2)\),显然过不了.不妨把 ...
随机推荐
- Windows10系统,安装appium之坑
本文主要讲述如何在 Windows10 系统上通过 npm 命令行安装 appium 应该有很多小伙伴在使用cnpm安装appium时遇到过各种报错,比如这样: 相信很多的小伙伴都会遇到这样的报错,导 ...
- 【cover-view、cover-image】 覆盖组件说明
cover-view.cover-image 这两类覆盖组件用于显示在一些特殊组件上方(map.video.canvas.camera.live-player.live-pusher). 这类组件一般 ...
- Visual Stdio Code编辑Mark Down
Visual Studio Code可以一边写Markdown一边预览了,而且不需要任何插件. 方法如下: 新建一个文件,以 .md 为后缀: Visual Studio Code 原生就支持高亮Ma ...
- windows store无法登陆的问题解决方案
Windows应用商店或商店Apps无法打开或闪退的可选方法 (仅用于10565之前的Windows 10版本) 右键点击任务栏,选择"属性",切换到"导航"选 ...
- Eclipse安装颜色主题,个性化你的IDE,让你的IDE焕然一新
我们都知道eclipse默认的颜色主题是白色的背景,但是如果想改变代码编辑区的背景颜色,需要怎么办呢? 今天给大家介绍一个非常赞的eclipse,可以很方便的根据自己的需求选择喜欢的颜色主题,其他的不 ...
- 王者荣耀交流协会beta冲刺贡献分分配结果
根据原来约定的(贡献分分配规则){http://www.cnblogs.com/gaoyb348/p/7828523.html} 总共20个任务,一共35分,那么一个任务1.75分. 冉华完成了9个任 ...
- 算法与数据结构3.3 calculator
★实验任务 小 V 发明了一个神奇的整数计算器: 给定一个合法的表达式,这个计算器能求出这个表达式的最终答案. 表达式可能包含: +:运算符,整数加法.如 1+1=2 -:运算符,整数减法.如 1-1 ...
- C++课堂作业2016.05.04
GitHub/object-oriented 作业题目 开课后的第一次作业,简单地写了一个类,用成员函数来实现计算圆的面积. [代码] main.cpp #include "Area.h&q ...
- Css入门课程 Css文本样式
文字是网页的非常基础的内容,文本的样式设置也是非常重要的 1 字体大小 font-size:绝对大小单位和相对大小单位,绝对大小单位有cm,mm in(厘米,毫米,英寸)等,这是大小不随屏幕分辨率大小 ...
- server2003 必要的系统优化和安全设置
修改远程桌面端口: Windows 2003系统中的远程终端服务是一项功能非常强大的服务,同时也成了入侵者长驻主机的通道,入侵者可以利用一些手段得到管理员账号和密码并入侵主机.下面,我们来看看如何通过 ...