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;
}