ゾンビ島 (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  阅读(15)  评论(0)    收藏  举报