Notas da aula: o caminho mais curto

Em um gráfico não líquido , o caminho mais curto refere-se ao caminho com o menor número de arestas entre dois vértices .
No diagrama de rede , o caminho mais curto refere-se ao caminho com a menor soma dos pesos na borda experimentados entre dois vértices . O caminho mais curto de um
único ponto de origem até outros vértices : Método Dijkstra, o caminho mais curto
entre qualquer par de vértices de O (n2) : Método floyed, o caminho mais curto do
ponto de origem único O (n3)
Descrição do problema: dado gráfico direcionado ponderado G = (V, E) e o ponto de origem v ∈ V, encontre o caminho mais curto de v para os vértices restantes em G.
Exemplo de aplicação - o problema da transmissão em rede de computadores: como encontrar a maneira mais econômica de enviar uma mensagem de um computador para todos os outros computadores na Internet.
Dijkstra propôs um algoritmo para gerar o caminho mais curto na ordem de aumentar o comprimento do caminho - o algoritmo de Dijkstra.
Entendendo o aumento do comprimento do caminho
Um gráfico com n vértices, calcule o caminho mais curto do vértice v para outros vértices (n-1) no gráfico e encontre n-1 menores caminhos no total.
Aumentar de acordo com o comprimento do caminho refere-se ao princípio de cálculo das estradas n-1, ou seja, o primeiro caminho mais curto (v, vi) é encontrado primeiro, o caminho mais curto entre todas as estradas n-1 e, em seguida, o segundo caminho mais curto ( v, vj) ...
Algoritmo de Dijkstra
Idéia básica:

1. Defina um conjunto S para armazenar os vértices do caminho mais curto encontrado, o estado inicial de S contém apenas o ponto de origem v,
2. Para vi∈VS, assuma que a aresta direcionada do ponto de origem v para vi é o caminho mais curto (o valor inicial do caminho mais curto de v para os vértices restantes).
3. Cada vez que um caminho mais curto v,…, vk é obtido, vk é adicionado ao conjunto S, e os caminhos v,…, vk, vi são comparados com a hipótese original e o caminho mais curto é tomado como o caminho mais curto.
O processo acima é repetido até que todos os vértices no conjunto V sejam adicionados ao conjunto S.
A característica do caminho mais curto com o menor comprimento (ou seja, o primeiro caminho mais curto) :
nesse caminho, deve haver apenas uma aresta e o peso nessa aresta é o menor.
As características do caminho mais curto com o próximo tamanho mais curto :
ele pode ter apenas dois casos: diretamente do ponto de origem até esse ponto (apenas uma aresta) ou do ponto de origem através do vértice v1 (o primeiro caminho mais curto O vértice ao qual está anexado) e, em seguida, alcance o vértice (composto por duas arestas).
As características do próximo caminho mais curto com o próximo comprimento mais curto :
ele pode ter quatro casos: diretamente do ponto de origem até o ponto (apenas uma aresta); ou do ponto de origem através do vértice v1 e depois para o vértice (por Composto por duas arestas); ou a partir do ponto de origem através do vértice v2 e, em seguida, alcance o vértice (duas arestas); ou a partir do ponto de origem através dos vértices v1, v2 e, em seguida, atinja o vértice (várias arestas).
As características do caminho mais curto restante :
ele é diretamente do ponto de origem até esse ponto (apenas uma aresta); ou passa do ponto de origem pelo vértice do caminho mais curto (o vértice no conjunto S) e atinge o vértice.
Prova
de correção O próximo caminho mais curto é um arco (v0, vx) ou um caminho que passa por alguns vértices em S e atinge vx.
Usando o método de reprovação: Suponha que exista um vértice vy no próximo caminho mais curto que não esteja em S, ou seja, esse caminho seja (v0, ..., vy, ..., vx). Obviamente, o comprimento de (v0, ..., vy) é menor que o comprimento de (v0, ..., vy, ..., vx), portanto, o próximo caminho mais curto deve ser (v0, ..., vy), que é o mesmo que o próximo caminho mais curto hipotético ( v0, ..., vy, ..., vx) contradizem! Portanto, não pode haver vértice vy não em S no próximo caminho mais curto, ou seja, a suposição não é verdadeira.
Estrutura de dados : estrutura de
armazenamento de gráfico : matriz de adjacência matriz de estrutura de armazenamento
dist [n] : cada componente dist [i] representa o comprimento do caminho mais curto atualmente encontrado desde o ponto inicial v até o ponto final vi. O estado inicial é: se houver um arco de v a vi, então dist [i] é o peso no arco, caso contrário, dist [i] é definido como ∞.
Caminho da matriz [n] : caminho [i] é uma sequência que representa o caminho mais curto atualmente encontrado desde o ponto inicial v até o ponto final vi. O estado inicial é: se houver um arco de v a vi, o caminho [i] é vvi; caso contrário, o caminho [i] é definido como uma string vazia.
Matriz s [n] : armazena o ponto de origem e o ponto final do caminho mais curto encontrado, cujo estado inicial é apenas um ponto de origem v.
As principais etapas do algoritmo de Dijkstra são as seguintes :
(1) g é um gráfico ponderado representado pela matriz de adjacência. S ← {v0}, dist [i] = g.arcs [v0] [vi], caminho [i] = “v0vi” ou “”; inicialize o comprimento do caminho de v0 para os vértices restantes como pesos;
(2) selecione vk, de modo que dist [vk] = min (dist [i] | vi∈VS), vk é o ponto final do próximo caminho mais curto da v0 obtido atualmente. Adicionar vk a S
(3) Modifique o comprimento do caminho mais curto de v0 para qualquer vértice vi no conjunto VS. Se dist [k] + g.arcs [k] [i] <dist [i], modifique dist [i] para dist [k] + g.arcs [k] [i] caminho [i] = caminho [k] ] + “Vi”
(4) Repita (2) e (3) n-1 vezes para encontrar o caminho mais curto entre v0 e o outro vértice no gráfico na ordem crescente do comprimento do caminho mais curto.

const int MAX=1000; 
void  Dijkstra(MGraph g, int v){        
	for ( i =0; i<g.vexnum ; i++){   
		dist[i]=g.arcs[v][i];                  
		if ( dist[i]!= MAX)                        
			path [i]=g.vertex[v]+g.vertex[i];
		else                       
			path[i]=“”;        
	}        
	S[0]=g.vertex[v];         
	num=1;  
	While (num<g.vextexNum){     
		k=0;     
		for(i=0;i<G.vertexNum;i++)            
			if((dist[i]<dist[k])   
				k=i     
		cout<<dist[k]<<path[k];     
		s[num++]=G.vertex[k];
		for(i=0;i<G.vertexNum;i++)              
			if(dist[k]+g.arc[k][i]<dist[i] {    
				dist[i]=dist[k]+g.arc[k][i];                        
				path[i]=path[k]+g.vertex[i];                
			} 
	} 
}             


Descrição do caminho mais curto entre cada par de vértices : dado um gráfico direcionado ponderado G = (V, E), para qualquer vértice vi, vj ∈ V (i ≠ j), encontre o caminho mais curto do vértice vi ao vértice vj .
Solução 1: Cada vez que um vértice é usado como ponto de origem, o algoritmo Dijkstra é chamado n vezes. Obviamente, a complexidade do tempo é O (n3).
Solução 2: o algoritmo de Floyd proposto por Freud para encontrar o caminho mais curto entre cada par de vértices tem uma complexidade de tempo de O (n3), mas a forma é mais simples.
A idéia básica do algoritmo de Floyd é a seguinte :
suponha que o gráfico g seja expresso pelo método da matriz de adjacência e encontre o caminho mais curto entre qualquer par de vértices vi e vj no gráfico g. (-1) Inicialize o menor comprimento do caminho de vi a vj a (vi, vj) e execute as seguintes n comparações e correções:
(0) Adicione o vértice v0 entre vi e vj e compare (vi, v0, vj) O comprimento do caminho de (vi, vj) e o caminho mais curto são tomados como o caminho mais curto de vi para vj e o número do vértice do meio não é maior que 0.
(1) Adicione os vértices v1 entre vi e vj para obter (vi,…, v1) e (v1,…, vj), onde: (vi,…, v1) é de vi a v1 e o número do vértice do meio não é maior que 0 O caminho mais curto de (v1,…, vj) é o caminho mais curto de v1 a vj e o número do vértice do meio não é maior que 0. Esses dois caminhos foram encontrados na etapa anterior. Compare (vi,…, v1,…, vj) com o caminho mais curto obtido na etapa anterior e o número de vértice intermediário de vi a vj não seja maior que 0 e use o caminho mais curto como vi a vj e o número de vértice intermediário não é O caminho mais curto maior que 1.
(2) Adicione o vértice v2 entre vi e vj para obter (vi,…, v2) e (v2,…, vj), onde: (vi,…, v2) é de vi a v2 e o número do vértice do meio não é maior que 1 O caminho mais curto de (v2,…, vj) é o caminho mais curto de v2 para vj e o número do vértice do meio não é maior que 1. Esses dois caminhos foram encontrados na etapa anterior. Compare (vi,…, v2,…, vj) com o caminho mais curto encontrado na etapa anterior e o número de vértice intermediário de vi a vj não é maior que 1 e use o caminho mais curto como vi a vj e o número de vértice intermediário não é O caminho mais curto maior que 2.
...
Projete
a estrutura de armazenamento do diagrama da estrutura de dados : a matriz da estrutura de armazenamento da matriz de adjacência ponderada
dist [n] [n] : armazena o menor comprimento do caminho obtido durante o processo de iteração. Fórmula de iteração :
dist-1 [i] [j] = arco [i] [j],
dist k [i] [j] = min {distk-1 [i] [j], distk-1 [i] [k ] + distk-1 [k] [j]}
0 ≤ k ≤
n -1 caminho da matriz [n] [n] : armazena o caminho mais curto de vi a vj, inicialmente o caminho [i] [j] = "vivj" .
Descrição do algoritmo Floyd-C ++

void Floyd(MGraph G) 
{     
	for (i=0; i<G.vertexNum; i++)                
		for (j=0; j<G.vertexNum; j++)        
		{           
			dist[i][j]=G.arc[i][j];           
			if (dist[i][j]!=)                 
				path[i][j]=G.vertex[i]+G.vertex[j];           
			else 
				path[i][j]="";
		}
		for (k=0; k<G.vertexNum; k++)                  
			for (i=0; i<G.vertexNum; i++)                   
				for (j=0; j<G.vertexNum; j++)                
					if (dist[i][k]+dist[k][j]<dist[i][j]) {
						dist[i][j]=dist[i][k]+dist[k][j];                     
						path[i][j]=path[i][k]+path[k][j];               
					} 
}
Publicado 48 artigos originais · Gosto 25 · Visita 2453

Acho que você gosta

Origin blog.csdn.net/qq_43628959/article/details/103333937
Recomendado
Clasificación