Luogu P3393 逃离僵尸岛【最短路】By cellur925

题目传送门

题目大意:(其实概括出来也就基本做完了hh)在一张有$n$个点,$m$条边的无向图上,有$k$个点是不能经过的,而与之距离不超过$s$的点,到他们会花费$Q$元,到其他点会花费$p$元,求1到$n$花费的最小价钱。



概括完题意也就非常明了了。我们需要把图上的点分为三类,这部分可以由一个$bfs$求得。

void bfs()
{
    while(!q1.empty())
    {
        int u=q1.front().second;
        int val=q1.front().first;q1.pop();
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(val+1<=s&&dan[v]==0)
                dan[v]=1,q1.push(make_pair(val+1,v));
        }
    }
}

之后就是裸的最短路了=w=,注意松弛的时候分类讨论&&开longlong&&最后得出答案的时候减去终点的花费(不住了)

Code

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define maxn 100090

using namespace std;
typedef long long ll;

int n,m,k,s,tot,P,Q;
int head[maxn],dan[maxn],vis[maxn];
ll dis[maxn];
struct node{
    int to,next,val;
}edge[maxn*4];
queue<pair<int,int> >q1;

void add(int x,int y)
{
    edge[++tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}

void bfs()
{
    while(!q1.empty())
    {
        int u=q1.front().second;
        int val=q1.front().first;q1.pop();
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(val+1<=s&&dan[v]==0)
                dan[v]=1,q1.push(make_pair(val+1,v));
        }
    }
}

void dijkstra()
{
    priority_queue<pair<ll,int> >q;
    for(int i=1;i<=n;i++) dis[i]=1e18;
    dis[1]=0;q.push(make_pair(0,1));
    while(!q.empty())
    {
        int u=q.top().second;q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dan[v]==-1) continue;
            if(dan[v]==0&&dis[v]>dis[u]+P)
            {
                dis[v]=dis[u]+P;
                q.push(make_pair(-dis[v],v));
            }
            if(dan[v]==1&&dis[v]>dis[u]+Q)
            {
                dis[v]=dis[u]+Q;
                q.push(make_pair(-dis[v],v));
            }
        }
    }
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&s);
    scanf("%d%d",&P,&Q);
    for(int i=1,x;i<=k;i++) scanf("%d",&x),dan[x]=-1,q1.push(make_pair(0,x));
    for(int i=1;i<=m;i++)
    {
        int x=0,y=0;
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    bfs();
    dijkstra();
    if(dan[n]==0) printf("%lld\n",dis[n]-P);
    else printf("%lld\n",dis[n]-Q);
    return 0;
}

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9847624.html

时间: 2024-10-12 04:26:47

Luogu P3393 逃离僵尸岛【最短路】By cellur925的相关文章

洛谷⑨月月赛Round2 P3393逃离僵尸岛[最短路]

题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际空港在N号城市,这两座城市没有被侵略.小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所

P3393 逃离僵尸岛

题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际空港在N号城市,这两座城市没有被侵略.小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所

洛谷P3393 逃离僵尸岛

题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际空港在N号城市,这两座城市没有被侵略.小a走每一段道路(从一个城市直接到达另外一个城市)得花一整个白天,所

题解——逃离僵尸岛(BFS+最短路+虚拟节点)

题解--逃离僵尸岛(BFS+最短路+虚拟节点) 一道很巧妙的最短路问题,细节也要注意 题面 Description 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际

题解 P3393 【逃离僵尸岛】

题解 P3393 [逃离僵尸岛] 题目链接 没错这题就是单元最短路径的裸题. 同时也可以练习一下多源BFS 在处理被占领点周围的"危险点"时我们可以使用bfs,对于k个被占领点一个一个BFS显然太慢没有B格了,所以我们可以多源BFS,也就是第一次就把所有的被占领点压到队列里. 染完色以后处理每个点的权值,危险点的权值设为q,安全点的权值设为p,被占领的点权值设为一个比较大的数. 然后从点1跑最短路径就行了. 总之这是一道有点细节的模板题,要开long long不然玄学错误 代码: /*

AC日记——逃离僵尸岛 洛谷 P3393

逃离僵尸岛 思路: spfa: 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 200005 #define maxque 1800056 #define INF 1e12 #define ll long long ll n,m,E[maxque],V[maxque],cnt,

逃离僵尸岛

[题目描述] 现有N个城市,城市之间有道路相连,一共有M条双向道路,保证没有自环和重边. 现有K个城市已经被僵尸控制,所以不能进入.若某个正常城市到某个僵尸城市的距离不超过S,则称此城市为危险城市. 小A住在1号城市,他想去N号城市避难,这两座城市没有被侵略.白天小A会走一段道路,晚上要住在所处城市.在正常城市需花费P元,而在危险城市,由于安保措施,所以会变贵,为Q元.所有危险城市的住宿花费相同,正常城市也是如此.且在1号城市和N号城市,小A不需要住店. 现询问从1号城市到N号城市所需要的最小花

Luogu P5122 [USACO18DEC]Fine Dining 最短路

先跑一遍n为起点最短路,再新开一个点,向有干草垛的点连一根边权为d[u]-w的有向边(很重要..我当时连的无向边,然后我死了.),相当于用价值抵消一部分边权, 然后以这个新的点为起点跑最短路就好了... #include<cstdio> #include<iostream> #include<cstring> #include<queue> #define pc(x) putchar(x) #define R register int using names

【题解】Luogu P1613 跑路 倍增+最短路

题里都说了$2^k$,明显倍增 因为跑路器的存在,不能直接跑最短路的原因: 如图,如果直接最短路从1号点到5号点的距离为3,需要3秒 而实际上走$1->5$这条边,因为$8=2^3$,只需1秒 $n≤50$直接无脑floyed随便跑 code 1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define ll long long 5 const int maxn=1e6+10; 6 inli