ゾンビ島 (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;
}
posted @ 2025-05-29 17:43  ZnHF  阅读(47)  评论(0)    收藏  举报