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;
    }
  • 相关阅读:
    Golang的安装包方法
    Debian kvm网络配置
    Debian-Linux配置网卡网络方法
    KVM虚拟机网络配置 Bridge方式,NAT方式
    WebRTC之框架与接口
    WebRTC
    关于golang.org/x包问题
    http内网转发
    linux服务器可以访问IP访问不了域名地址
    golang--生成某区间的随机数
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4661973.html
Copyright © 2011-2022 走看看