HDU-4360 As long as Binbin loves Sangsang

记录每个节点从四个方向来的最优值,用了那个spfa后,因为要标记入队,所以就会牵涉到一个节点的自环现象,所以这里就直接在队列里面记录其当前距离,不进行队列优化,也过了。该题的边竟然是双向的。

代码如下:

#include <cstring>

#include <cstdlib>

#include <cstdio>

#include <algorithm>

#include <queue>

using namespace std;



typedef long long int Int64;



int N, M, idx, mp[255], head[1500], step[1500][4];



Int64 dis[1500][4]; // 保留四状态的最短路



struct Edge

{

    int v, d, k, next;

}e[30000];



struct Node

{

    int v, k, step;

    Int64 dis;

}info, pos;



void addEdge(int x, int y, int d, int k)

{

    ++idx;

    e[idx].v = y, e[idx].d = d, e[idx].k = k;

    e[idx].next = head[x];

    head[x] = idx;

}



void spfa()

{

    int v;

    queue<Node>q;

    memset(dis, 0x3f, sizeof (dis));

    memset(step, 0, sizeof (step));

    info.dis = 0, info.v = 1, info.k = 3;

    info.step = 0;

    q.push(info);

    while (!q.empty()) {

        pos = q.front();

        q.pop();

        for (int i = head[pos.v]; i != -1; i = e[i].next) {

            int k = (pos.k + 1) % 4;

            v = e[i].v;

            if (e[i].k == k) {

                if (dis[v][k] > pos.dis + e[i].d || dis[v][k] == pos.dis + e[i].d && step[v][k] < pos.step + 1) {

                    dis[v][k] = pos.dis + e[i].d;

                    step[v][k] = pos.step + 1;

                    info.v = v, info.dis = dis[v][k];

                    info.k = k, info.step = step[v][k];

                    q.push(info);

                }

            }

        }

    }

    if (dis[N][3] == dis[N+1][0]) { // 没有更改过

        puts("Binbin you disappoint Sangsang again, damn it!");

    }

    else {

        printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n", dis[N][3], step[N][3]/4);    

    }

}



int main()

{

    int T, x, y, d, ca = 0;

    char s[5];

    mp['L'] = 0, mp['O'] = 1, mp['V'] = 2, mp['E'] = 3;

    scanf("%d", &T);

    while (T--) {

        memset(head, 0xff, sizeof (head));

        idx = -1;

        scanf("%d %d", &N, &M);

        for (int i = 0; i < M; ++i) {

            scanf("%d %d %d %s", &x, &y, &d, s);

            addEdge(x, y, d, mp[s[0]]); // 保留所有的边信息

            addEdge(y, x, d, mp[s[0]]);

            // 自身结点也可以成环 

        }

        printf("Case %d: ", ++ca);

        spfa();

    }

    return 0;

}

你可能感兴趣的:(long)