洛谷P3393 逃离僵尸岛

Posted SilverNebula

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷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,表示一条无向边

输出格式:

一个整数表示最低花费

输入输出样例

输入样例#1:
13 21 1 1
1000 6000
7
1 2
3 7
2 4
5 8
8 9
2 5
3 4
4 7
9 10
10 11
5 9
7 12
3 6
4 5
1 3
11 12
6 7
8 11
6 13
7 8
12 13
输出样例#1:
11000

说明

对于20%数据,N<=50

对于100%数据,2 ≦ N ≦ 100000, 1 ≦ M ≦ 200000, 0 ≦ K ≦ N - 2, 0 ≦ S ≦ 100000

1 ≦ P < Q ≦ 100000

 

今天真的是毫无状态啊,各种敲错变量看错题意,这么一道水题WA了六七次……

 

先DFS搜出每一个危险城市,再跑spfa就行。需要long long

之前还写了一个BFS版本的,WA掉就换了DFS(后来发现错因不在BFS)

BFS代码一并附在下面,那份代码没有加被感染城市不能走的判定,也没有用long long,当然WA咯,不过大致算法还是明确的。

 1 /**/
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 using namespace std;
 8 const long long inf=1000000000ll*1000000000ll+10ll;
 9 const int mxn=500000;
10 struct edge{
11     int v,nxt;
12 }e[mxn];
13 int hd[mxn],cnt=0;
14 void add_edge(int u,int v){
15     e[++cnt].v=v;e[cnt].nxt=hd[u];hd[u]=cnt;
16     return;
17 }
18 int n,m,k,s;
19 long long P,Q;
20 int kp[mxn];//被感染城市 
21 bool da[mxn];//危险标记
22 int head=0,tl=0;
23 int q[mxn];
24 long long dis[mxn];
25 bool vis[mxn];
26 bool ban[mxn];
27 void dfs(int u)
28 {
29     if(dis[u]<=s)da[u]=1;
30     if(dis[u]==s)return;
31     for(int i=hd[u];i;i=e[i].nxt){
32         int v=e[i].v;if(ban[v])continue;
33         if(dis[v]>dis[u]+1){
34             dis[v]=dis[u]+1;
35             dfs(v);
36         }
37     }
38     return;
39 }
40 
41 bool inq[mxn];
42 void SPFA(int x){
43     for(int i=1;i<=n;i++)dis[i]=inf;
44     head=1;tl=1;
45     q[head]=x;
46     dis[x]=0;
47     inq[x]=1;
48     while(head!=tl+1){
49         int u=q[head];head=(head+1)%150000;
50         for(int i=hd[u];i;i=e[i].nxt){
51             int v=e[i].v;long long cst=(da[v])?Q:P;
52             if(ban[v])continue;
53             if(dis[v]>dis[u]+cst){
54                 dis[v]=dis[u]+cst;
55                 if(!inq[v]){
56                     tl=(tl+1)%150000;
57                     q[tl]=v;
58                 }
59             }
60         }
61         inq[u]=0;
62     }
63     return;
64 }
65 int main(){
66     scanf("%d%d%d%d",&n,&m,&k,&s);
67     int i,j;
68     scanf("%lld%lld",&P,&Q);
69     int u,v;
70     for(i=1;i<=k;i++){
71         scanf("%d",&kp[i]);
72         ban[kp[i]]=1;
73     }
74     for(i=1;i<=m;i++){
75         scanf("%d%d",&u,&v);
76         add_edge(u,v);
77         add_edge(v,u);
78     }
79     for(int i=1;i<=n;i++)dis[i]=inf;
80     for(i=1;i<=k;i++){
81         dis[kp[i]]=0;
82         dfs(kp[i]);
83     }
84     SPFA(1);
85     if(da[n])dis[n]-=Q;
86     else dis[n]-=P;
87     printf("%lld\\n",dis[n]);
88     return 0;
89 }

 

 

 1 /**/
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 using namespace std;
 8 const int mxn=500000;
 9 struct edge{
10     int v,nxt;
11 }e[mxn];
12 int hd[mxn],cnt=0;
13 void add_edge(int u,int v){
14     e[++cnt].v=v;e[cnt].nxt=hd[u];hd[u]=cnt;
15     return;
16 }
17 int n,m,k,s;
18 int P,Q;
19 int kp[mxn];//被感染城市 
20 bool da[mxn];//危险标记
21 int head=0,tl=0;
22 int q[mxn];
23 int dis[mxn];
24 bool vis[mxn];
25 void BFS(int x){
26     memset(vis,0,sizeof vis);
27     int i,j;
28     head=1;    tl=1;
29     q[tl]=x;vis[x]=1;da[x]=1;
30     dis[x]=0;
31     int u,v;
32     while(head!=tl+1){
33         u=q[head];head=(head+1)%150000;
34         for(i=hd[u];i;i=e[i].nxt){
35             v=e[i].v;
36             if(!vis[v]){
37                 dis[v]=dis[u]+1;
38                 if(dis[v]<s){
39                     tl=(tl+1)%150000;
40                     q[tl]=v;
41                 }
42                 da[v]=1;
43                 vis[v]=1;
44             }
45         }
46     }
47     return;
48 }
49 bool inq[mxn];
50 void SPFA(int x){
51     memset(dis,0x3f,sizeof dis);
52     head=1;tl=1;
53     q[head]=x;
54     dis[x]=0;
55     inq[x]=1;
56     while(head!=tl+1){
57         int u=q[head];head=(head+1)%150000;
58         for(int i=hd[u];i;i=e[i].nxt){
59             int v=e[i].v;int cst=(da[v])?Q:P;
60             if(dis[v]>dis[u]+cst){
61                 dis[v]=dis[u]+cst;
62                 if(!inq[v]){
63                     tl=(tl+1)%150000;
64                     q[tl]=v;
65                 }
66             }
67         }
68         inq[u]=0;
69     }
70     return;
71 }
72 int main(){
73     scanf("%d%d%d%d",&n,&m,&k,&s);
74     int i,j;
75     scanf("%d%d",&P,&Q);
76     int u,v;
77     for(i=1;i<=k;i++){
78         scanf("%d",&kp[i]);
79     }
80     for(i=1;i<=m;i++){
81         scanf("%d%d",&u,&v);
82         add_edge(u,v);
83         add_edge(v,u);
84     }
85     for(i=1;i<=k;i++){
86         BFS(kp[i]);
87     }
88     SPFA(1);
89     if(da[n])dis[n]-=Q;
90     else dis[n]-=P;
91     printf("%d\\n",dis[n]);
92     return 0;
93 }
BFS

 

以上是关于洛谷P3393 逃离僵尸岛的主要内容,如果未能解决你的问题,请参考以下文章

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

题解 P3393 逃离僵尸岛

P3393 逃离僵尸岛

Luogu P3393 逃离僵尸岛

图论-最短路P3393逃离僵尸岛

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