【洛谷P3393】逃离僵尸岛
这两天有点忙 昨天做的题目都没传上来
P3393 逃离僵尸岛
题目描述
小 a 住的国家被僵尸侵略了!小 a 打算逃离到该国唯一的国际空港逃出这个国家。
该国有 \(N\) 个城市,城市之间有道路相连。一共有 \(M\) 条双向道路。保证没有自环和重边。
其中 \(K\) 个城市已经被僵尸控制了,如果贸然闯入就会被感染 TAT...所以不能进入。由其中任意城市经过不超过 \(S\) 条道路就可以到达的别的城市,就是危险城市。换句话说只要某个城市到任意被僵尸控制的城市距离不超过 \(S\),就是危险的。
小 a 住在 \(1\) 号城市,国际空港在 \(N\) 号城市,这两座城市没有被侵略。小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所以晚上要住旅店。安全的的城市旅馆比较便宜要 \(P\) 元,而被危险的城市,旅馆要进行安保措施,所以会变贵,为 \(Q\) 元。所有危险的城市的住宿价格一样,安全的城市也是。在 \(1\) 号城市和 \(N\) 城市,不需要住店。
小 a 比较抠门,所以他希望知道从 \(1\) 号城市到 \(N\) 号城市所需要的最小花费。
输入数据保证存在路径,可以成功逃离。输入数据保证他可以逃离成功。
输入格式
第一行 4 个整数 \(N,M,K,S\)。
第二行两个整数 \(P,Q\)。
接下来 \(K\) 行,每行一个整数 \(c_i\),表示僵尸侵占的城市编号。
接下来 \(M\) 行,\(a_i,b_i\),表示一条无向边。
输出格式
一个整数表示最低花费。
输入输出样例 #1
输入 #1
13 21 1 1
1000 6000
7
1 2
3 7
2 4
5 8
8 9
2 5
3 4
4 7
9 10
10 11
5 9
7 12
3 6
4 5
1 3
11 12
6 7
8 11
6 13
7 8
12 13
输出 #1
11000
说明/提示

对于 \(20\%\) 数据,\(N\le 50\)。
对于 \(100\%\) 数据,\(2\le N\le 10^5\),\(1\le M\le 2\times 10^5\),\(0\le K\le N - 2\),\(0\le S\le 10^5\),\(1\le P< Q\le 10^5\)。
解法&&个人感想
我们可以看出 要标记出所有的危险城市 需要跑最短路
但是是全源的诶?怎么办?
我们有一个新的思路:超级源点(虚点)
我们设置一个虚点0 把所有被僵尸占领的城市都的接到这个点上
这样相当于只需要跑一次最短路
然后对于点权最短路 再跑一次就行了
下面看代码:
#include<bits/stdc++.h>
#define ll long long
#define maxm 1000005
#define maxn 100005
using namespace std;
int n,m,k,s;
int P,Q;
int x,y,z,tot,c;
int head[maxm],nex[maxm],ver[maxm];
int city[maxn];
ll d[maxn];
int vis[maxn];
int price[maxn];
void add(int x,int y){
ver[++tot]=y;
nex[tot]=head[x];
head[x]=tot;
}
void dijkstra(int sx){
priority_queue<pair<int,int>>q;
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
d[sx]=0;
q.push(make_pair(0,sx));
while(!q.empty()){
int x=q.top().second;q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(d[y]>d[x]+1){
d[y]=d[x]+1;
q.push(make_pair(-d[y],y));
}
}
}
}
void dijkstra_2(int sx){
priority_queue<pair<ll,int>>q;
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
d[sx]=0;
q.push(make_pair(0,sx));
while(!q.empty()){
int x=q.top().second;q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==n+1||city[y]==2) continue;
if(d[y]>d[x]+price[y]){
d[y]=d[x]+price[y];
q.push(make_pair(-d[y],y));
}
}
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&k,&s);
scanf("%d%d",&P,&Q);
for(int i=1;i<=k;i++){
scanf("%d",&c);
city[c]=2;
add(n+1,c);
add(c,n+1);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dijkstra(n+1);
for(int i=1;i<=n;i++){
if(d[i]<=s+1&&city[i]!=2) city[i]=1;
}
for(int i=1;i<=n;i++){
if(i==1||i==n) continue;
else if(city[i]==0) price[i]=P;
else if(city[i]==1) price[i]=Q;
}
dijkstra_2(1);
printf("%lld",d[n]);
system("pause");
return 0;
}


浙公网安备 33010602011771号