As long as Binbin loves Sangsang

题目连接

  • 题意:

    给定一个无向图,每个边有两个属性,长度和一个字母‘L‘,’O‘,‘V’,‘E‘中的一个。从1点开始到达n点,每次必须按照L -> O -> V -> E -> ... -> E的顺序,到达终点时候必须经过E边

  • 分析:

    对于这种对边的限制,比较简单的方法是将一个点拆成若干个点。因为经过’L‘到达点p的状态和经过‘O‘到达点p的状态时不一样的,第一个之后只能经过’O‘边,而第二个只能经过‘V‘边,所以经过不同的边到达同一个点的时候对应的状态应该分开,也就是将点拆分成四个点,分别表示经过四种边到达p点。

  • 注意:

    图可以有自环,也可以只有一个点

    路径必须至少有一个LOVE

    路径长度尽可能小,长度若相等,那么LOVE的数量尽可能多

Dijkstra方法:(一个点的时候直接特判,避免不必要的麻烦)

const LL INF = 1e18;
const int MAXV = 10000;

struct Edge
{
    LL from, to, dist;
};

struct HeapNode
{
    LL d, u, num;
    bool operator < (const HeapNode& rhs) const
    {
        return d > rhs.d;
    }
};

struct Dijkstra
{
    int n;              //n:点数 m:临时变量
    vector<Edge> edges; //存储所有的边
    vector<int> G[MAXV];//每个点的所有相邻边序号
    bool done[MAXV];    // 是否已永久标号
    LL d[MAXV];         // s起点到各个点的距离
    LL num[MAXV];

    void init(int n)
    {
        this->n = n;
        for(int i = 0; i < n; i++) G[i].clear();
        edges.clear();
    }

    void AddEdge(int from, int to, int dist)
    {
        G[from].push_back(edges.size());
        edges.push_back((Edge) { from, to, dist });
    }

    void dijkstra(int s)
    {
        priority_queue<HeapNode> Q;
        for(int i = 0; i < n; i++) d[i] = INF;
        CLR(num, 0);
        d[s] = 0;
        memset(done, 0, sizeof(done));
        Q.push((HeapNode) { 0, s, 0 });
        while(!Q.empty())
        {
            HeapNode x = Q.top();
            Q.pop();
            int u = x.u;
            if(done[u]) continue;
            done[u] = true;
            for(int i = 0; i < G[u].size(); i++)
            {
                Edge& e = edges[G[u][i]];
                if (d[e.to] == d[u] + e.dist)
                    num[e.to] = max(num[e.to], num[x.u] + 1);
                if(d[e.to] > d[u] + e.dist)
                {
                    d[e.to] = d[u] + e.dist;
                    num[e.to] = num[x.u] + 1;
                    Q.push((HeapNode) { d[e.to], e.to, num[e.to] });
                }
            }
        }
    }
} dij;

LL chk[4];

int main()
{
    int T;
    RI(T);
    FE(kase, 1, T)
    {
        REP(i, 4) chk[i] = INF;
        int n, m, u, v, d, op;
        char type;
        RII(n, m);
        dij.init(n << 2);
        REP(i, m)
        {
            scanf("%d%d%d %c", &u, &v, &d, &type);
            u--; v--;
            if (type == 'L') op = 0;
            else if (type == 'O') op = 1;
            else if (type == 'V') op = 2;
            else op = 3;
            chk[op] = min(chk[op], (LL)d);
            dij.AddEdge(u + (op + 3) % 4 * n, v + op * n, d);
            dij.AddEdge(v + (op + 3) % 4 * n, u + op * n, d);
        }
        printf("Case %d: ", kase);
        if (n == 1)
        {
            REP(i, 4)
                if (chk[i] == INF)
                {
                    puts("Binbin you disappoint Sangsang again, damn it!");
                    goto end;
                }
            printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n"
                   , chk[0] + chk[1] + chk[2] + chk[3], 1);
            end:;
        }
        else
        {
            dij.dijkstra(3 * n);
            if (dij.d[4 * n - 1] == INF)
                puts("Binbin you disappoint Sangsang again, damn it!");
            else
            {
                printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %I64d LOVE strings at last.\n"
                       , dij.d[4 * n - 1], dij.num[4 * n - 1] / 4);
            }
        }
    }
    return 0;
}

spfa方法:(一个点也是特判,加点方式与Dijkstra相同)

const LL INF = 1e18;
const int MAXV = 10000;

struct Edge
{
    int from, to, dist;
};

struct SPFA
{
    int n;
    LL d[MAXV];
    int num[MAXV];
    vector<Edge> edges;
    vector<int> G[MAXV];
    bool inq[MAXV];
    void init(int n)
    {
        this->n = n;
        edges.clear();
        REP(i, n)
            G[i].clear();
    }
    void AddEdge(int from, int to, int dist)
    {
        G[from].push_back(edges.size());
        edges.push_back((Edge) {from, to, dist});
    }
    void spfa(int s)
    {
        queue<int> q;
        CLR(inq, false);
        CLR(num, 0);
        REP(i, n) d[i] = INF;
        d[s] = 0;
        q.push(s); inq[s] = true;
        while (!q.empty())
        {
            int u = q.front();
            q.pop(); inq[u] = false;
            REP(i, G[u].size())
            {
                Edge& e = edges[G[u][i]];
                if (d[e.to] == d[u] + e.dist && num[u] + 1 > num[e.to])
                {
                    num[e.to] = num[u] + 1;
                    if (!inq[e.to])
                    {
                        q.push(e.to);
                        inq[e.to] = true;
                    }
                }
                if(d[e.to] > d[u] + e.dist)
                {
                    d[e.to] = d[u] + e.dist;
                    num[e.to] = num[u] + 1;
                    if (!inq[e.to])
                    {
                        q.push(e.to);
                        inq[e.to] = true;
                    }
                }
            }
        }
    }
} spfa;

LL chk[4];

int main()
{
    int T;
    RI(T);
    FE(kase, 1, T)
    {
        REP(i, 4) chk[i] = INF;
        int n, m, u, v, d, op;
        char type;
        RII(n, m);
        spfa.init(n << 2);
        REP(i, m)
        {
            scanf("%d%d%d %c", &u, &v, &d, &type);
            u--; v--;
            if (type == 'L') op = 0;
            else if (type == 'O') op = 1;
            else if (type == 'V') op = 2;
            else op = 3;
            chk[op] = min(chk[op], (LL)d);
            spfa.AddEdge(u + (op + 3) % 4 * n, v + op * n, d);
            spfa.AddEdge(v + (op + 3) % 4 * n, u + op * n, d);
        }
        printf("Case %d: ", kase);
        if (n == 1)
        {
            REP(i, 4)
                if (chk[i] == INF)
                {
                    puts("Binbin you disappoint Sangsang again, damn it!");
                    goto end;
                }
            printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n"
                   , chk[0] + chk[1] + chk[2] + chk[3], 1);
            end:;
        }
        else
        {
            spfa.spfa(3 * n);
            if (spfa.d[4 * n - 1] == INF)
                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"
                       , spfa.d[4 * n - 1], spfa.num[4 * n - 1] / 4);
            }
        }
    }
    return 0;
}

顺便弄一些自己的测试数据,方便查错。

4 4

1 2 1 L

2 1 1 O

1 3 1 V

3 4 1 E

ans:4, 1

4 4

1 2 1 L

2 3 1 O

3 4 1 V

4 1 1 E

ans:no

12  12

1 5 10 L

5 6 10 O

6 7 10 V

7 12 10 E

1 2 1 L

2 3 1 O

3 4 1 V

4 8 1 E

8 9 1 L

9 10 1 O

10 11 1 V

11 12 33 E

ans:40, 2

12  12

1 5 10 L

5 6 10 O

6 7 10 V

7 12 10 E

1 2 1 L

2 3 1 O

3 4 1 V

4 8 1 E

8 9 1 L

9 10 1 O

10 11 1 V

11 12 34 E

ans:40, 1

1 4

1 1 1 L

1 1 1 O

1 1 1 V

1 1 1 E

ans:4, 1

2 8

1 1 2 L

1 1 1 O

1 1 1 V

1 1 1 E

1 2 3 L

2 1 1 O

1 2 1 V

2 1 1 E

ans:5, 1

1 3

1 1 1 L

1 1 1 O

1 1 1 E

ans:no

11 11

1 2 1 L

2 3 1 O

3 4 348 V

4 11 1000 E

1 5 50 L

5 6 50 O

6 7 50 V

7 8 50 E

8 9 50 L

9 10 50 O

10 4 50 V

ans:1350 2

As long as Binbin loves Sangsang

时间: 2024-08-04 08:52:27

As long as Binbin loves Sangsang的相关文章

HDU - 4360As long as Binbin loves Sangsang最短路问题多状态记录

HDU - 4360 As long as Binbin loves Sangsang Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description Binbin misses Sangsang so much. He wants to meet with Sangsang as soon as possible. Now Binbin downloads

HDU 4360 As long as Binbin loves Sangsang(SPFA)

As long as Binbin loves Sangsang Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2779    Accepted Submission(s): 627 Problem Description Binbin misses Sangsang so much. He wants to meet with Sa

hdu 4360 As long as Binbin loves Sangsang(最短路)

hdu 4360 As long as Binbin loves Sangsang Description Binbin misses Sangsang so much. He wants to meet with Sangsang as soon as possible. Now Binbin downloads a map from ELGOOG.There are N (1<=N<=1,314) cities in the map and these cities are connect

HDU 4360 As long as Binbin loves Sangsang spfa

题意: 给定n个点m条边的无向图 每次必须沿着LOVE走,到终点时必须是完整的LOVE,且至少走出一个LOVE, 问这样情况下最短路是多少,在一样短情况下最多的LOVE个数是多少. 有自环. #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <iostream> #include <algorithm> using names

hdu4360 As long as Binbin loves Sangsang spfa变形

题意:给定n个点m条边的无向图,每次必须沿着LOVE走,到终点时必须是完整的LOVE,且至少走出一个LOVE,问这样情况下最短 路是多少,在一样短情况下最多的LOVE个数是多少.注意:有自环!(见底下的数据) 思路:其实本质就是个最短路,用spfa就好.注意自环的特殊处理,详见代码: /********************************************************* file name: hdu4360.cpp author : kereo create tim

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小

2012 Multi-University #7

最短路+拆点 A As long as Binbin loves Sangsang 题意:从1走到n,每次都是LOVE,问到n时路径是连续多个"LOVE"的最短距离.秀恩爱不想吐槽. 分析:在普通的最短路上有寻路的限制,把一个点看成4个点,表示通过某一个字符到该点的最短距离.

Codeforces 444A DZY Loves Physics(图论)

题目链接:Codeforces 444A DZY Loves Physics 题目大意:给出一张图,图中的每个节点,每条边都有一个权值,现在有从中挑出一张子图,要求子图联通,并且被选中的任意两点,如果存在边,则一定要被选中.问说点的权值和/边的权值和最大是多少. 解题思路:是图论中的一个结论,最多两个节点,所以枚举两条边就可以了.我简单的推了一下,2个点的情况肯定比3个点的优. 假设有3个点a,b,c,权值分别为A,B,C 现a-b,b-c边的权值分别为u,v 那么对于两点的情况有A+Bu,B+

[HDU5677]ztr loves substring

ztr loves substring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description ztr love reserach substring.Today ,he has n string.Now ztr want to konw,can he take out exactly k palindrome from all substrin