【题解】LuoGu3393:逃离僵尸岛

版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/81914161

原题传送门
题目描述

小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,表示一条无向边

输出格式:
一个整数表示最低花费
输入样例
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
输出样例
11000
对于100%数据,2 ≦ N ≦ 100000, 1 ≦ M ≦ 200000, 0 ≦ K ≦ N - 2, 0 ≦ S ≦ 100000

【题解】
读完题目我发现这是一道裸的最短路~~~
只是多了一个判断是否为危险城市的步骤
本题分为以下几个步骤

  • 把感染的城市标记,这些城市是不通的,并放进一个bfs队列
  • 从感染的城市出发进行bfs,把遍历到的距离<=s的标记为危险城市(危险城市与感染城市是不同的)
  • 以1为起点,做最短路,我刚学了dijkstra堆优化,所以用了这个方法,本题也可以用SPFA

嗯没错,这就是一道模板题,解释一下我的代码的各个变量的用途

  • heap 堆(由于我用的是pascal,所以是手打堆)
  • q,d 用于bfs,q记录点的序号,d记录该点离最近的感染城市的距离
  • edge,head 数组模拟链表存图
  • flag 标记感染城市 danger 标记危险城市 vis 用于dijkstra
  • dis 表示距离,用于dijkstra

注意:开int64(long long),并且初始化dis也要弄得很大很大,比2147483647还要大

Code:

var
    heap:array[0..1000000] of record
        num,dis:int64;
    end;
    edge:array[0..1000000] of record
        t,next:int64;
    end;
    head,q,d,dis:array[0..1000000] of int64;
    vis,danger,flag:array[0..1000000] of boolean;
    n,m,k,s,p,qq,x,y,z,h,t,num,len,e,w:int64;
    i:longint;

procedure add(x,y:int64);

begin
    inc(num);
    edge[num].t := y;
    edge[num].next := head[x];
    head[x] := num;
end;

procedure swap(var x,y:int64);
var
    tmp:int64;

begin
    tmp := x; x := y; y := tmp;
end;

procedure push(x,y:int64);
var
    i:longint;

begin
    inc(len);
    heap[len].num := x; heap[len].dis := y;
    i := len;
    while i > 1 do
    begin
        if heap[i].dis < heap[i >> 1].dis then
        begin
            swap(heap[i].num,heap[i >> 1].num);
            swap(heap[i].dis,heap[i >> 1].dis);
            i := i >> 1;
        end else break;
    end;
end;

procedure pop;
var
    i,x:longint;

begin
    heap[1].num := heap[len].num; heap[1].dis := heap[len].dis;
    dec(len); i := 1;
    while (i << 1) <= len do
    begin
        if ((i << 1 or 1) > len) or (heap[i << 1].dis < heap[i << 1 or 1].dis) then
            x := i << 1 else x := i << 1 or 1;
        if heap[i].dis > heap[x].dis then
        begin
            swap(heap[i].num,heap[x].num);
            swap(heap[i].dis,heap[x].dis);
            i := x;
        end else break;
    end;
end;

begin
    readln(n,m,k,s);
    readln(p,qq);
    for i := 1 to k do
    begin
        readln(q[i]);
        flag[q[i]] := true;
    end;
    for i := 1 to m do
    begin
        readln(x,y);
        add(x,y); add(y,x);
    end;
    t := k;
    while h < t do
    begin
        inc(h);
        if d[h] = s then break;
        i := head[q[h]];
        while i <> 0 do
        begin
            e := edge[i].t;
            if not danger[e] then
            begin
                danger[e] := true;
                inc(t);
                q[t] := e; d[t] := d[h] + 1;
            end;
            i := edge[i].next;
        end;
    end;
    for i := 2 to n do dis[i] := maxlongint * maxlongint;
    heap[1].num := 1; heap[1].dis := 0; len := 1;
    while len > 0 do
    begin
        x := heap[1].num; y := heap[1].dis;
        pop;
        if vis[x] then continue;
        vis[x] := true;
        i := head[x];
        while i <> 0 do
        begin
            e := edge[i].t;
            if flag[e] then
            begin
                i := edge[i].next;
                continue;
            end;
            if danger[e] then w := qq else w := p;
            if e = n then w := 0;
            if dis[e] > y + w then
            begin
                dis[e] := y + w;
                push(e,dis[e]);
            end;
            i := edge[i].next;
        end;
    end;
    writeln(dis[n]);
end.

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/81914161