zoukankan      html  css  js  c++  java
  • luogu 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)

    第二行2个整数(P,Q)

    接下来K行,ci,表示僵尸侵占的城市

    接下来M行,ai,bi,表示一条无向边

    输出格式

    一个整数表示最低花费


    首先我们需要知道哪些城市是危险的:

    根据广搜的性质(第一次搜到的答案就是最优值),我们将被占领的城市入队,然后用广搜将它们拓展从而求出与最近被占城市距离在S以内的城市。

    然后我们需要计算最短路:

    安全的城市点权就是P,危险的就是Q,而被占领的城市不能去,干脆让点权变成inf。然后用Dijkstra即可。

    时间复杂度为O((N+M)log(N+M))。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define maxn 100001
    #define maxm 200001
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,m,K,S,P,Q;
    inline int read(){
        register int x(0),f(1); register char c(getchar());
        while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
        while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    
    struct edge{
        int to,next;
        edge(){}
        edge(const int &_to,const int &_next){ to=_to,next=_next; }
    }e[maxm<<1];
    int head[maxn],k;
    inline void add(const int &u,const int &v){ e[k]=edge(v,head[u]),head[u]=k++; }
    
    int val[maxn];
    bool vis[maxn];
    queue< pair<int,int> > que;
    inline void bfs(){
        while(que.size()){
            int u=que.front().first,w=que.front().second; que.pop();
            for(register int i=head[u];~i;i=e[i].next){
                int v=e[i].to;
                if(!vis[v]&&w+1<=S) que.push(make_pair(v,w+1)),vis[v]=true;
            }
        }
    }
    
    long long dis[maxn];
    bool used[maxn];
    priority_queue< pair<long long,int>,vector< pair<long long,int> >,greater< pair<long long,int> > > q;
    inline void Dijkstra(){
        memset(dis,0x3f,sizeof dis);
        q.push(make_pair(0,1)),dis[1]=0;
        while(q.size()){
            int u=q.top().second; q.pop();
            if(used[u]) continue; used[u]=true;
            for(register int i=head[u];~i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]>dis[u]+val[v]) dis[v]=dis[u]+val[v],q.push(make_pair(dis[v],v));
            }
        }
    }
    
    int main(){
        memset(head,-1,sizeof head);
        n=read(),m=read(),K=read(),S=read(),P=read(),Q=read();
        for(register int i=1;i<=K;i++){
            int x=read();
            que.push(make_pair(x,0)),val[x]=inf,vis[x]=true;
        }
        for(register int i=1;i<=m;i++){
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        bfs();
        
        for(register int i=1;i<=n;i++){
            if(vis[i]&&!val[i]) val[i]=Q;
            if(!vis[i]) val[i]=P;
        }
        val[1]=val[n]=0;
        Dijkstra();
        printf("%lld
    ",dis[n]);
        return 0;
    }
    
  • 相关阅读:
    System.Web.HtppRuntime.cs
    Code:Tree
    Code-Helper-Web:CacheHelper.cs
    Code-Helper-Web:CookieHelper.cs
    ORACLE数据库常用查询二
    涂抹Oracle笔记2:数据库的连接-启动-关闭
    windows下常用的操作命令及dos命令
    涂抹Oracle笔记1-创建数据库及配置监听程序
    表空间满处理方法
    SQL内连接-外连接join,left join,right join,full join
  • 原文地址:https://www.cnblogs.com/akura/p/11067726.html
Copyright © 2011-2022 走看看