Luogu P3393 逃离僵尸岛

题目传送门

\(\rm{kkksc03}\)说是模板题,但像我这种蒟蒻觉得万分艰难


这道题目的核心在于求出所有的危险城市,我们可以一次性将所有的被占领的城市全部加入队列里,然后扩展危险城市

还有一点就是点权最短路,具体看代码吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
int read(){
    int k=0; char c=getchar();
    for(;c<'0'||c>'9';) c=getchar();
    for(;c>='0'&&c<='9';c=getchar())
      k=k*10+c-48;
    return k;
}
bool js[100010];
int pon[100010];
struct zzz{
    int t,nex;
}e[200010<<2]; int head[100010],tot;
void add(int x,int y){
    e[++tot].t=y;
    e[tot].nex=head[x];
    head[x]=tot;
}
struct hhh{
    int k,len;
};
queue <hhh> q; queue <int> q2;
LL dis[100010]; bool vis[100010],wrning[100010];
int main(){
    int n=read(),m=read(),k=read(),s=read(),p1=read(),p2=read();
    for(int i=1;i<=k;i++){
        int x=read(); q.push(hhh{x,s}); js[x]=1;
        wrning[x]=1;
    }
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        add(x,y); add(y,x);
    }
    while(!q.empty()){ //扩展危险城市
        hhh k=q.front(); q.pop();
        if(!k.len) continue;
        for(int i=head[k.k];i;i=e[i].nex){
            if(js[e[i].t]) continue;
            js[e[i].t]=1;
            q.push(hhh{e[i].t,k.len-1});
        }
    }
    for(int i=2;i<=n-1;i++) pon[i]= (js[i]? p2:p1);
    for(int i=1;i<=n+1;i++) dis[i]=(LL)922337203685;
    pon[n+1]=(LL)922336854775; dis[1]=0;
    q2.push(1); vis[1]=1;
    while(!q2.empty()){  //点权最短路
        int k=q2.front(); q2.pop(); vis[k]=0;
        for(int i=head[k];i;i=e[i].nex){
            if(wrning[e[i].t]) continue;
            if(dis[e[i].t]>dis[k]+pon[e[i].t]){
                dis[e[i].t]=dis[k]+pon[e[i].t];
                if(!vis[e[i].t]){
                    vis[e[i].t]=1; q2.push(e[i].t);
                }
            }
        }
    }
    cout<<dis[n];
    return 0;
}
posted @ 2019-11-14 09:26  MorsLin  阅读(133)  评论(0编辑  收藏  举报