【图论-最短路】【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)\),显然过不了.不妨把 ...
随机推荐
- (C#)设计模式之装饰模式
1.装饰模式 动态的给一个对象添加一些额外的职责,就添加功能来说,装饰模式比生成子类更加灵活.*装饰模式是为已有功能动态添加更多功能的一种方式.*装饰模式将原有类中的核心职责与装饰功能分离.简化了原有 ...
- 166. Nth to Last Node in List
Description Find the nth to last element of a singly linked list. The minimum number of nodes in lis ...
- 小程序开发中,纯css实现内容收起折叠功能
不多说,直接上代码: wxml页面: <!--收起折叠 begin--> <view style='width:100%;background:#fff;border-top:1px ...
- UVa 401 - Palindromes 解题报告 - C语言
1.题目大意 输入字符串,判断其是否为回文串或镜像串.其中,输入的字符串中不含0,且全为合法字符.以下为所有的合法字符及其镜像: 2.思路 (1)考虑使用常量数组而不是if或switch来实现对镜像的 ...
- Python3 标准库:os
1.重命名 import os os.rename('test.txt','x.txt') #重命名文件或目录 import os os.renames('a/123.txt','a/b/h.txt' ...
- Cannot retrieve repository metadata (repomd.xml) for repository: base. Please verify its path and try again YUM报错
1.挂盘 ----- 2.# mount /dev/sr0 /media/ mount: block device /dev/sr0 is write-protected, mounting ...
- vue.js 创建组件 子父通信 父子通信 非父子通信
1.创建组件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- 动态规划——最长上升子序列LIS及模板
LIS定义 一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序列(ai1 ...
- 【OpenGL】无法启动此程序,因为计算机中丢失 glut32.dll。尝试重新安装该程序以解决此问题。
运行OpenGL程序的时候报错,如图: 解决方法:把glut32.dll复制到C:\Windows\SysWOW64目录下,而不是像网上教程那样复制到C:\Windows\System32目录下. 原 ...
- 访问方式由http改为https curl:(51)
系统访问由http变为https,先申请了CA证书,然后win下浏览器访问时没问题的,但是linux下通过curl的方式访问就报错: curl:(51) SSLcertificate subject ...