HDU [4725] El camino más corto en Nya Graph [El camino más corto + diagrama de construcción]

Descripción

Este es un problema muy fácil, su tarea es simplemente calcular el camino más corto en un gráfico, y solo hay que cambiar un poco el algoritmo. Si no entiende una palabra de este párrafo, simplemente continúe.
El gráfico de Nya es un gráfico no dirigido con "capas". Cada nodo en el gráfico pertenece a una capa, hay N nodos en total.
Puede moverse de cualquier nodo en la capa x a cualquier nodo en la capa x + 1, con un costo C, ya que las carreteras son bidireccionales, también se permite mover de la capa x + 1 a la capa x con el mismo costo.
Además, hay M bordes adicionales, cada uno conectando un par de nodos u y v, con un costo w.
Ayúdenos a calcular la ruta más corta del nodo 1 al nodo N.

Entrada 

La primera línea tiene un número T (T <= 20), que indica el número de casos de prueba.
Para cada caso de prueba, la primera línea tiene tres números N, M (0 <= N, M <= 105) y C (1 <= C <= 103), que es el número de nodos, el número de bordes adicionales y el costo de moverse entre capas adyacentes.
La segunda línea tiene N números li (1 <= li <= N), que es la capa del ith nodo al que pertenece.
Luego vienen N líneas cada una con 3 números, u, v (1 <= u, v <= N, u <> v) yw (1 <= w <= 104), lo que significa que hay un borde adicional, conectando un par de nodos u y v, con costo w.

Salida

Para el caso de prueba X, envíe primero "Caso # X:", luego envíe el costo mínimo al pasar del nodo 1 al nodo N.
Si no hay soluciones, envíe -1.

Entrada de muestra

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 

 Salida de muestra

Caso # 1: 2

Caso # 2: 3

La idea principal:

Dados N puntos (numerados del 1 al N) y M bordes derechos bidireccionales, cada borde está conectado a dos puntos, lo que indica la longitud de la ruta; cada punto tiene su propio valor de capa, qué punto pertenece a qué capa; Además de los bordes dados, las dos capas adyacentes pueden cruzarse desde cualquier punto de la capa x a cualquier punto de la capa x + 1 o la capa x-1, y el costo es C (no la capa cruzada, cuesta C, pero Eligiendo cruzar la capa sin tomar la ruta de conexión existente cuesta C), solicite el punto más corto del punto 1 al punto N.

Análisis:

Se requiere la ruta más corta. En base a los datos del sujeto, hemos utilizado el algoritmo Dijkstra optimizado para el montón. La clave es considerar cómo construir el mapa.

Existe el concepto de capa de capa, todos los puntos en la misma capa pueden tomar el camino del costo de capa cruzada c. Entonces podemos construir un nodo virtual para cada capa para tratar el concepto de capas. La distancia desde este nodo virtual a todos los puntos de la capa es 0.

Cabe señalar que los bordes de los nodos virtuales y puntos en la capa no pueden ser bordes no dirigidos. Debido a que el requisito en el título es que los puntos en la capa no pueden cruzarse por el concepto de la capa (la ruta de conexión entre los dos puntos no está conectada por el concepto de la capa), si es un borde no dirigido, causará el punto en la capa Los nodos virtuales se visitan sin costo alguno, lo que no está en línea con el título.

Entonces creamos dos nodos virtuales para cada capa, como se muestra a continuación.

Específicamente, usamos i + n para representar el nodo virtual 1 de la capa i-ésima para el borde entrante de la capa, e i + 2n para el nodo virtual 2 de la capa i-ésima para el borde saliente de la capa.

Después de construir el mapa, solo use 1 como punto de origen y ejecute Dijkstra nuevamente.

Vea el código para una explicación específica.

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

 

30 artículos originales publicados · ganó 5 · 900 visitas

Supongo que te gusta

Origin blog.csdn.net/qq_42840665/article/details/102885198
Recomendado
Clasificación