zoukankan      html  css  js  c++  java
  • P

    题意:有N个点和N层..一层有X个点(0<=X<=N).两邻两层间有一条路花费C。还有M条小路在两个点之间。问从第一个点走到第N个点最短路是多少...

    可以考虑在每一层增加一个点,这个点到上下层的距离是C,与本层的距离是0;

    T的很惨,不太明白为什么,翻了一下大神的博客,发现这个要把每层拆成两个点来算的,要是只拆成一个点那么本层到本层的点都会是0了

    ////////////////////////////////////////////////////

    时间卡的很恶心,还需要双端队列,如果新加入的点的值比队列顶端的额值小就放在方面,否则就放在下面(不明白优化在那里了.......)
    #include<stdio.h>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<algorithm>
    #include<string.h>
    #include<math.h>
    using namespace std;

    const int maxn = 1000005;
    const int maxm = 100005;
    const int oo = 0xfffffff;

    struct node
    {
        int u, v, c, next;
    }e[maxn];
    int head[maxm*3], dis[maxm*3];
    bool use[maxm*3];

    void Add(int u, int v, int w, int k)
    {
        e[k].u = u;
        e[k].v = v;
        e[k].c = w;
        e[k].next = head[u];
        head[u] = k;
    }
    void spfa()
    {
        deque<int> Q;
        Q.push_back(1);

        while(Q.size())
        {
            int i = Q.front();Q.pop_front();
            use[i] = false;

            for(int j=head[i]; j!=0; j=e[j].next)
            {
                int u=e[j].u, v=e[j].v, w=e[j].c;

                if(dis[u]+w < dis[v])
                {
                    dis[v] = dis[u] + w;

                    if(use[v] == false)
                    {
                        use[v] = true;
                        if(Q.size() && dis[v] < dis[Q.front()])
                            Q.push_front(v);
                        else
                            Q.push_back(v);
                    }
                }
            }
        }
    }

    int main()
    {
        int T, t=1;

        scanf("%d", &T);

        while(T--)
        {
            int i, N, M, C, u, v, w, x, k=1;

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

            memset(head, 0sizeof(head));

            for(i=1; i<=N; i++)
            {
                //本层拆出来的点是 出i+N, 入i+2*N

                dis[i] = dis[i+N] = dis[i+2*N] = oo;

                if(i != N)
                {
                    Add(i+N, i+2*N+1, C, k++);
                    Add(i+N+1, i+2*N, C, k++);
                }

                scanf("%d", &x);//节点i属于第x层

                Add(i, x+N, 0, k++);
                Add(x+2*N, i, 0, k++);
            }

            for(i=1; i<=M; i++)
            {
                scanf("%d%d%d", &u, &v, &w);
                Add(u, v, w, k++);
                Add(v, u, w, k++);
            }

            dis[1] = 0;
            spfa();

            if(dis[N] == oo)
                printf("Case #%d: -1 ", t++);
            else
                printf("Case #%d: %d ", t++, dis[N]);
        }

        return 0;
    }
  • 相关阅读:
    PAT 甲级 1027 Colors in Mars
    PAT 甲级 1026 Table Tennis(模拟)
    PAT 甲级 1025 PAT Ranking
    PAT 甲级 1024 Palindromic Number
    PAT 甲级 1023 Have Fun with Numbers
    PAT 甲级 1021 Deepest Root (并查集,树的遍历)
    Java实现 蓝桥杯VIP 算法训练 无权最长链
    Java实现 蓝桥杯VIP 算法训练 无权最长链
    Java实现 蓝桥杯 算法提高 抽卡游戏
    Java实现 蓝桥杯 算法提高 抽卡游戏
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4661973.html
Copyright © 2011-2022 走看看