HDU [4725] The Shortest Path in Nya Graph [The shortest path + construction diagram]

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

The main idea:

Given N points (numbered 1 to N) and M bidirectional right edges, each edge is connected to two points, indicating the length of the path; each point has its own layer value, which point belongs to which layer; In addition to the given edges, the adjacent two layers can cross from any point of the x layer to any point of the x + 1 layer or x-1 layer, and the cost is C (not the cross layer, it costs C, but Choosing to cross the layer without taking the existing connection path costs C), ask the shortest point from point 1 to point N.

analysis:

The shortest path is required. Based on the subject data, we have used the heap-optimized Dijkstra algorithm. The key is to consider how to build the map.

There is the concept of layer layer, all points in the same layer can take the path of cross-layer cost c. Then we can construct a virtual node for each layer to deal with the concept of layers. The distance from this virtual node to all points in the layer is 0.

It should be noted that the edges of the virtual nodes and points in the layer cannot be undirected edges. Because the requirement in the title is that the points in the layer cannot be crossed by the concept of the layer (the connection path between the two points is not connected by the concept of the layer), if it is an undirected edge, it will cause the point in the layer Virtual nodes visit each other at no cost, which is not in line with the title.

So we create two virtual nodes for each layer, as shown below.

Specifically, we use i + n to represent the virtual node 1 of the i-th layer for the incoming edge of the layer, and i + 2n for the virtual node 2 of the i-th layer for the outgoing edge of the layer.

After building the map, just use 1 as the source point and run Dijkstra again.

See the code for specific explanation.

//#include <bits/stdc++.h>
#include <iostream>
#include <sstream>
#include <cstring>
#include <queue>
#include <map>
#include <vector>

using namespace std;

const int maxn=1e5+5;
const int INF=0x3f3f3f3f;

int vis[3*maxn],dis[3*maxn];  //注意这里要开三倍的空间 

struct node{
	int nxt,w;
};

int e,n,c;
vector<int> layer[maxn]; 
vector<node> gra[3*maxn];		//注意这里要开三倍的空间

struct point{
    int val,id;
    point(int id,int val):id(id),val(val) {}
    bool operator <(const point &x)const{ 
        return val>x.val;
    }
};

void dijkstra(int s){
    memset(vis,0,sizeof(vis));
    for(int i=1; i<=3*n; i++)
        dis[i]=INF;
 
    priority_queue<point> q;
    q.push(point(s,0));
    vis[s]=1;
    dis[s]=0;
    while(!q.empty()){
        int cur=q.top().id;
        q.pop();
        vis[cur]=1;
        for(int i=0; i < gra[cur].size() ; i++){
            int id=gra[cur][i].nxt;
            int cost=gra[cur][i].w;
            if(!vis[id]&&dis[id]>dis[cur]+cost){
            	dis[id]=dis[cur]+cost;
            	q.push(point(id,dis[id]));
            }
        }
    }
}

int main(){
	int t,tmp,u,v,w,cas=0;
	scanf("%d",&t);
	while(t--){
		++cas;
		scanf("%d%d%d",&n,&e,&c);
		//初始化 
		for(int i=1;i<=n;i++){
			layer[i].clear();
			gra[i].clear();
			gra[i+n].clear();
			gra[i+2*n].clear();
		}
		//确定各个层内的节点 
		for(int i=1;i<=n;i++){
			scanf("%d",&tmp);
			layer[tmp].push_back(i);
		}
		//加入额外的固定无向边 
		for(int i=1;i<=e;i++){
			scanf("%d%d%d",&u,&v,&w);
			node nn;
			nn.nxt=v;
			nn.w=w;
			gra[u].push_back(nn);
			nn.nxt=u;
			gra[v].push_back(nn);
		}
		for(int i=1;i<=n;i++){
			for(int j=0;j<layer[i].size();j++){
				node nn;
				nn.w=0;
				nn.nxt=layer[i][j];
				gra[i+n].push_back(nn);	//虚拟节点1(i+n)指向层中点,边权值为0 
			}
			for(int j=0;j<layer[i].size();j++){
				node nn;
				nn.w=0;
				nn.nxt=i+2*n;
				gra[layer[i][j]].push_back(nn);	//层中点指向虚拟节点2(i+2*n),边权值为0 
			}
			//该层指向后一层的边 
			if(i!=n){
				node nn;
				nn.w=c;
				nn.nxt=i+n+1;
				gra[i+2*n].push_back(nn);
			}
			//该层指向前一层的边 
			if(i!=1){
				node nn;
				nn.w=c;
				nn.nxt=i+n-1;
				gra[i+2*n].push_back(nn);
			}
		}
		//求最短路 
		dijkstra(1);
		printf("Case #%d: %d\n",cas,dis[n]==INF?-1:dis[n]);
	} 
	return 0;
}

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/102885198
Recommended