1. 程式人生 > >計蒜客 ACM-ICPC 2018 瀋陽賽區網路預賽 D. Made In Heaven(A*演算法第K短路)

計蒜客 ACM-ICPC 2018 瀋陽賽區網路預賽 D. Made In Heaven(A*演算法第K短路)

Description:

One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. However, Pucci the father somehow knows it and wants to stop her. There are NN spots in the jail and MM roads connecting some of the spots. JOJO finds that Pucci knows the route of the former (K1)(K-1)

-th shortest path. If Pucci spots JOJO in one of these K1K-1 routes, Pucci will use his stand Whitesnake and put the disk into JOJO’s body, which means JOJO won’t be able to make it to the destination. So, JOJO needs to take the KK-th quickest path to get to the destination. What’s more, JOJO only has T
T
units of time, so she needs to hurry.

JOJO starts from spot SS, and the destination is numbered EE. It is possible that JOJO’s path contains any spot more than one time. Please tell JOJO whether she can make arrive at the destination using no more than TT units of time.

Input:

There are at most 50

50 test cases.

The first line contains two integers NN and MM (1N1000,0M10000)(1 \leq N \leq 1000, 0 \leq M \leq 10000). Stations are numbered from 11 to NN.

The second line contains four numbers S,E,KS, E, K and TT ( 1S,EN1 \leq S,E \leq N, SES \neq E, 1K100001 \leq K \leq 10000, 1T1000000001 \leq T \leq 100000000 ).

Then MM lines follows, each line containing three numbers U,VU, V and WW (1U,VN,1W1000)(1 \leq U,V \leq N, 1 \leq W \leq 1000) . It shows that there is a directed road from UU-th spot to VV-th spot with time WW.

It is guaranteed that for any two spots there will be only one directed road from spot AA to spot BB (1A,BN,AB)(1 \leq A,B \leq N, A \neq B), but it is possible that both directed road KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲lt;A,B> and directed road KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲lt;B,A> exist.

All the test cases are generated randomly.

Output:

One line containing a sentence. If it is possible for JOJO to arrive at the destination in time, output "yareyaredawa" (without quote), else output "Whitesnake!" (without quote).

Sample Input:

2 2 1 2 2 14 1 2 5 2 1 4

Sample Output:

yareyaredawa

題目連結

判斷S到E的第K短路是否小於T,直接套A*演算法模板判斷第K短路距離。

AC程式碼:

#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 5;

struct Link {
    int V, Weight, Next;
};

Link edges[maxn << 1];
int Head[maxn];
int Tot;
// 反向邊
Link Reverseedges[maxn << 1];
int ReverseHead[maxn];
int ReverseTot;

// 鏈式前向星存圖初始化
void Init() {
    Tot = 0;
    memset(Head, -1, sizeof(Head));
    ReverseTot = 0;
    memset(ReverseHead, -1, sizeof(ReverseHead));
}

// 加邊建圖
void AddEdge(int U, int V, int Weight) {
    edges[++Tot] = Link {V, Weight, Head[U]};
    Head[U] = Tot;
    // 用反向邊另建圖
    Reverseedges[++ReverseTot] = Link {U, Weight, ReverseHead[V]};
    ReverseHead[V] = ReverseTot;
}

int N, M;
int S, E, K, T;
int Dis[maxn];

struct Cmp {
    bool operator() (const int &A, const int &B) {
        return Dis[A] > Dis[B];
    }
};

// 利用反向邊圖求各點到終點的最短路
void Dijkstra(int Start) {
    priority_queue<int, vector<int>, Cmp> Que;
    memset(Dis, INF, sizeof(Dis));
    Dis[Start] = 0;
    Que.push(Start);
    while (!Que.empty()) {
        int U = Que.top(); Que.pop();
        for (int i = ReverseHead[U]; i != -1; i = Reverseedges[i].Next) {
            if (Dis[Reverseedges[i].V] > Dis[U] + Reverseedges[i].Weight) {
                Dis[Reverseedges[i].V] = Dis[U] + Reverseedges[i].Weight;
                Que.push(Reverseedges[i].V);
            }
        }
    }
}

struct AStarNode {
    int F, G, Point;
    // A*核心:F=G+H(Point),這裡H(Point)=Dis[Point]
    bool operator < (const AStarNode &A) const {
        if (F == A.F) {
            return G > A.G;
        }
        return F > A.F;
    }
};

// A*演算法求第K短路
int AStar(int Start, int End) {
    int Cnt = 0;
    priority_queue<AStarNode> Que;
    // 此題相同點不算最短路
    if (Start == End) {
        K++;
    }
    // 起點與終點不連通
    if (Dis[Start] == INF) {
        return -1;
    }
    Que.push(AStarNode {Dis[Start], 0, Start});
    while (!Que.empty()) {
        AStarNode Keep = Que.top(); Que.pop();
        if (Keep.Point == End) {
            Cnt++;
            if (Cnt == K) {
                // 返回第K短路長度
                return Keep.G;
            }
        }
        for (int i = Head[Keep.Point]; i != -1; i = edges[i].Next) {
            AStarNode Temp;
            Temp.Point = edges[i].V;
            Temp.G = Keep.G + edges[i].Weight;
            Temp.F = Temp.G + Dis[Temp.Point];
            Que.push(Temp);
        }
    }
    return -1;
}

int main(int argc, char *argv[]) {
    while (~scanf("%d%d", &N, &M)) {
        Init();
        scanf("%d%d%d%d", &S, &E, &K, &T);
        for (int i = 0, U, V, C; i < M; ++i) {
            scanf("%d%d%d", &U, &V, &C);
            AddEdge(U, V, C);
        }
        Dijkstra(E);
        int Ans = AStar(S, E);
        if (Ans > T || Ans == -1) {
            printf("Whitesnake!\n");
        }
        else {
            printf("yareyaredawa\n");
        }
    }
    return 0;
}