ゾンビ島 (Zombie Island) 题解
题意简述
给定一张含有 \(N\) 个点 \(M\) 条边的无向图。有 \(K\) 个点上存在僵尸,这 \(K\) 个点不能经过。从存在僵尸的点出发,通过不超过 \(S\) 条边可以到达的点称为“危险城镇”,其余的称为“安全城镇”。
经过一个编号不为 \(1\) 或 \(N\) 的点时,若该点为“安全城镇”,则需要花费 \(P\) 元,若该点为“危险城镇”,则需要花费 \(Q\) 元。
求从编号为 \(1\) 的点走到编号为 \(N\) 的点的最少花费是多少。
题目分析
首先分别从 \(K\) 个存在僵尸的点出发,使用 BFS 算法求出通过不超过 \(S\) 条边就可以到达的点,并标记为“危险城镇”,没有被标记的就是“安全城镇”。再从编号为 \(1\) 的点出发,使用 BFS 算法求出到达编号为 \(N\) 的点的最小花费即可。
具体地,在求最小花费的过程中,若将要经过的点为“安全城镇”,则花费增加 \(Q\) 元,若将要经过的点为“危险城镇”,则花费增加 \(P\) 元。
代码
#include<bits/stdc++.h>
#define int long long//答案可能超过 int 的范围
using namespace std;
inline int read(){register int t1=0,t2=0;register char x=getchar();while(x<'0' ||x>'9'){if(x=='-') t2|=1;x=getchar();}while(x>='0' && x<='9'){t1=(t1<<1)+(t1<<3)+(x^48),x=getchar();}return t2?-t1:t1;}//快读
inline void write(int x){register int sta[35],top=0;if(x<0) putchar('-'),x=-x;do{sta[top++]=x%10,x/=10;}while(x);while(top) putchar(sta[--top]+48);}//快输
int n,m,k,s,P,Q,c[100005],dis[100005],dan[100005];
bool vis[100005];
struct node{
int x,y;
}temp;
bool operator <(const node &x,const node &y){
return x.y>y.y;
}
priority_queue<node> q;
vector<int> v[100005];
queue<node> qu;
signed main(){
#ifdef cxy
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
m=read();
k=read();
s=read();
P=read();
Q=read();
for(int i=1;i<=k;i++){
c[i]=read();
dan[c[i]]=1;
qu.push((node){c[i],0});
}
for(int i=1;i<=m;i++){
int t1=read(),t2=read();
v[t1].push_back(t2);
v[t2].push_back(t1);
}
while(!qu.empty()){
temp=qu.front();
qu.pop();
for(int i=0;i<v[temp.x].size();i++){
if(!dan[v[temp.x][i]] && temp.y+1<=s){
dan[v[temp.x][i]]=2;
qu.push((node){v[temp.x][i],temp.y+1});
}
}
}//求出每一个“危险城镇”
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
vis[1]=1;
q.push((node){1,0});
while(!q.empty()){
temp=q.top();
q.pop();
for(int i=0;i<v[temp.x].size();i++){
if(vis[v[temp.x][i]] || dan[v[temp.x][i]]==1) continue;
if(v[temp.x][i]==n){
vis[v[temp.x][i]]=1;
dis[v[temp.x][i]]=temp.y;
}
else if(dan[v[temp.x][i]]==2){
if(dis[v[temp.x][i]]>temp.y+Q){
dis[v[temp.x][i]]=temp.y+Q;
vis[v[temp.x][i]]=1;
q.push((node){v[temp.x][i],dis[v[temp.x][i]]});
}
}
else{
if(dis[v[temp.x][i]]>temp.y+P){
dis[v[temp.x][i]]=temp.y+P;
vis[v[temp.x][i]]=1;
q.push((node){v[temp.x][i],dis[v[temp.x][i]]});
}
}
}
}//求出最小花费
write(dis[n]);
putchar('\n');
return 0;
}