The Shortest Path in Nya Graph HDU - 4725 分层最短路 Dijkstra(最短路专题)

题目描述

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 <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), 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.

题目大意: 给你n个点,这n个点分别属于某一个层,在同一个层中所有点相互之间的距离为0,对于在 x 层中的所有点,其通向 第 x-1 层 和第 x+1 层的点都有一条双向道路,且权值为 c 。再给你一些双向道路。问你从点1到点n的最短距离是多少。

 

解题思路:   首先这题的难点就在于建图,因为最多会给你1e5个点,如果对每层中的每个点都按常规方法建图,一定会t。         

                   建图方法如下

                    

                   这种建图方式大大减少了边的总数,边的总数大概从N*N 变成了 5N+2N 条 ,点的总数变成了 2N。

代码:

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long 
#define MOD 998244353 
#define INF 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))  
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int NUM = 200005;
const int maxn = 200005;
struct node{
   int to,w;
   node(int b,int c){to=b;w=c;}
};
vector<node>e[NUM];
int dis[NUM];
bool vis[NUM];
int n,m,c;
int l[200005];
int a[200005];
struct cmp
{
   bool operator()(int a,int b)
   {
      return dis[a]>dis[b];
   }
};
void Dijkstra()
{
    priority_queue<int,vector<int>,cmp>Q;
    for(int i=0;i<=maxn;i++){
        dis[i]=INF;
        vis[i]=false;
    }
    dis[1]=0;
    Q.push(1);
    while(!Q.empty()){
        int u=Q.top();
        Q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].to;
            int w=e[u][i].w;
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                Q.push(v);
            }
        } 
    }
}
int main()
{
    int t,tt;
    cin>>t;
    tt=t;
    while(t--){
        for(int i=1;i<=maxn;i++){
            a[i]=0;
            l[i]=0;
            e[i].clear();
        }
        scanf("%d %d %d",&n,&m,&c);
        for(int i=1;i<=n;i++){
          scanf("%d",&l[i]);
          a[l[i]]=1;
        }
        //分层建图
        for(int i=1;i<=n;i++){
            e[l[i]+n].push_back(node(i,0));
            if(a[l[i]-1]){
               e[i].push_back(node(l[i]+n-1,c));
            }
            if(a[l[i]+1]){
               e[i].push_back(node(l[i]+n+1,c));
            }
        }
        for(int i=1;i<=m;i++){
            int a,b,d;
            scanf("%d %d %d",&a,&b,&d);
            e[a].push_back(node(b,d));
            e[b].push_back(node(a,d));
        }
        Dijkstra();
        if(dis[n]<INF){
            printf("Case #%d: %d\n",tt-t,dis[n]);
        }else{
            printf("Case #%d: -1\n",tt-t);
        }

        
    }
    return 0;
}

 

posted @ 2020-07-27 22:23  hachuochuo  阅读(126)  评论(0编辑  收藏  举报