zoukankan      html  css  js  c++  java
  • 洛谷 P3393 逃离僵尸岛

    洛谷

    这道题目其实是最短路裸题。

    首先看到题目,要求的到“被占点”距离不大于S的点,自然想到了以“被占点”为源点,求一遍最短路,处理出“危险点”。

    可是问题来了,“被占点”有k个,总不能求k次最短路吧,于是我就想到,将所有“被占点”归纳在0这一个外加点上,视作一个点,当“被占点”们与其他点连边时,就用0与其相连,“被占点”之间不连边。

    然后,跑一边spfa,边权全都是1(当然也可以广搜),再扫一遍,找出危险点。

    最后,以1为源点,求一遍最短路,当到达点为“危险点”时,边权为Q,为1或n点时,边权为0,为“被占点”时,边权为inf。输出dis[n]即可。

    注意,要开long long~

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=100010;
    const long long inf=214748364701;
    queue <int> q;
    int n,m,k,ss,P,Q;
    long long dis[N],w[N<<2];
    int s[N<<2][2],o[N],cnt;
    bool ocp[N],vis[N],dgs[N];
    inline void add(int,int);
    
    inline void spfa(int now)
    {
        memset(vis,0,sizeof(vis));
        for (int i=1;i<=n;++i) dis[i]=inf;
        while (!q.empty()) q.pop();
        q.push(now);dis[now]=0;vis[now]=1;
        while (!q.empty()) {
            int x=q.front();
            for (int i=o[x];i;i=s[i][1]) {
                int y=s[i][0];
                if (dis[y]>dis[x]+w[i]) {
                    dis[y]=dis[x]+w[i];
                    if (!vis[y])
                        vis[y]=1,q.push(y);
                }
            }
            vis[x]=0;q.pop();
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m>>k>>ss>>P>>Q;
        int x,y;
        for (int i=1;i<=k;++i)
            cin>>x,ocp[x]=1;
        for (int i=1;i<=m;++i) {
            cin>>x>>y;
            if (ocp[x]&&ocp[y]) continue;
            if (ocp[x]) add(0,y),add(y,0);
            else if (ocp[y]) add(0,x),add(x,0);
            else add(x,y),add(y,x);
        }
        for (int i=1;i<=cnt;++i) w[i]=1;
        spfa(0);
        for (int i=1;i<=n;++i)
            if (dis[i]<=ss) dgs[i]=1;
        for (int i=1;i<=cnt;++i) {
            if (dgs[s[i][0]]) w[i]=Q;
            else if (ocp[s[i][0]]) w[i]=inf;
            else w[i]=P;
            if (s[i][0]==1||s[i][0]==n) w[i]=0;
        }
        spfa(1);
        cout<<dis[n]<<endl;
        return 0;
    }
    
    inline void add(int x,int y)
    {
        s[++cnt][0]=y;s[cnt][1]=o[x];o[x]=cnt;
    }
    
  • 相关阅读:
    数仓备机DN重建:快速修复你的数仓DN单点故障
    深度学习分类任务常用评估指标
    云小课 | MRS基础入门之HDFS组件介绍
    华为云数据库GaussDB(for Cassandra)揭秘第二期:内存异常增长的排查经历
    为什么vacuum后表还是继续膨胀?
    Go 自定义日志库
    Go time包
    Go 文件操作
    Go 包相关
    【程序人生】跟小伙伴们聊聊我有趣的大学生活和我那两个好基友!
  • 原文地址:https://www.cnblogs.com/fushao2yyj/p/9512394.html
Copyright © 2011-2022 走看看