zoukankan      html  css  js  c++  java
  • hdu4725最短路变形 添加点

    The Shortest Path in Nya Graph

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4872    Accepted Submission(s): 1122


    Problem Description
    This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
    The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
    You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
    Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
    Help us calculate the shortest path from node 1 to node N.
     

    Input
    The first line has a number T (T <= 20) , indicating the number of test cases.
    For each test case, first line has three numbers N, M (0 <= N, M <= 105) and C(1 <= C <= 103), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
    The second line has N numbers li (1 <= li <= N), which is the layer of ith node belong to.
    Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 104), which means there is an extra edge, connecting a pair of node u and v, with cost w.
     

    Output
    For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
    If there are no solutions, output -1.
     

    Sample Input
    
    
    2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4
     

    Sample Output
    Case #1: 2 Case #2: 3
     
     
     
    题意: 有n个地点,m条边,每条边耗费w,每个点又属于一些集合,相邻的集合之间的点可以直接通行,耗费c。现在求1到n的最少费用。
     
    思路:可以把集合当做一个点,从集合到集合内的点费用为0,点到相邻的集合费用为c,这样就既保证了不用暴力枚举相邻集合里面的每个点,有保证相邻集合里的点的最短路(表达能力不好 -。-#!)。
    就是这张图的意思:
    然后一遍dij+heap就好。
     
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<string>
    #include<time.h>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 1000000001
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    using namespace std;
    const int MAXN = 100010;
    struct node
    {
        int to;
        int val;
        int next;
    }edge[MAXN * 10];
    int pre[MAXN*3],vis[MAXN*3],dis[MAXN*3],n,m,k,c,ind;
    int num[MAXN],ok[MAXN];
    void add(int x,int y,int z)
    {
        edge[ind].to = y;
        edge[ind].val = z;
        edge[ind].next = pre[x];
        pre[x] = ind ++;
    }
    struct Node
    {
        int p;
        ll val;
        Node(){}
        Node(int fp,int fval):p(fp),val(fval){}
        friend bool operator < (Node fa,Node fb){
            return fa.val > fb.val;
        }
    };
    void dij(int s)
    {
        priority_queue<Node>fq;
        for(int i = 1; i <= k; i++){
            dis[i] = INF;
            vis[i] = 0;
        }
        dis[s] = 0;
        fq.push(Node(s,0));
        while(!fq.empty()){
            Node tp = fq.top();
            fq.pop();
            vis[tp.p] = 1;
            for(int i = pre[tp.p]; i != -1; i = edge[i].next){
                int t = edge[i].to;
                if(!vis[t] && dis[t] > dis[tp.p] + edge[i].val){
                    dis[t] = dis[tp.p] + edge[i].val;
                    fq.push(Node(t,dis[t]));
                }
            }
        }
    }
    int main()
    {
        int t,ff = 0;
        scanf("%d",&t);
        while(t--){
            memset(num,0,sizeof(num));
            memset(ok,0,sizeof(ok));
            scanf("%d%d%d",&n,&m,&c);
            int x;
            ind = 0;
            memset(pre,-1,sizeof(pre));
            for(int i = 1; i <= n; i++){
                scanf("%d",&x);
                ok[x] = 1;
                num[i] = x;
            }
            for(int i = 1; i <= n; i++){//点与集合之间连边
                add(n+num[i],i,0);
                if(num[i] > 1)add(i,n+num[i]-1,c);
                if(num[i] < n)add(i,n+num[i]+1,c);
            }
            int y,z;
            for(int i = 1; i <= m; i++){
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
                add(y,x,z);
            }
            //cout<<k<<endl;
            k = 2 * n;
            dij(1);
            printf("Case #%d: ",++ff);
            if(dis[n] >= INF){
                printf("-1
    ");
            }
            else {
                printf("%d
    ",dis[n]);
            }
        }
        return 0;
    }
     
  • 相关阅读:
    HTML常用标签
    JSP是什么?
    Linux下叹号!的用法
    原码、反码、补码、移码之间的关系和转换
    关于联想超极本出现蓝屏Default Boot Device Missing or Boot Failed的解决办法
    基于UEFI和GPT模式下U盘安装windows8.1和Linux双启动教程
    horizon服务
    neutron网络服务部署
    neutron网络服务
    cinder存储服务
  • 原文地址:https://www.cnblogs.com/sweat123/p/5463617.html
Copyright © 2011-2022 走看看