El entrenamiento de algoritmo _ problema del camino más corto

formación algoritmo de la teoría de grafos _ el algoritmo del camino más corto

Aquí Insertar imagen Descripción

Cortas de origen único problema del camino

BFS algoritmo es incapaz de resolver el problema del camino más corto gráfico ponderado, por debajo de
Aquí Insertar imagen Descripción
S a B debe ser de una sola fuente más corta S -> A -> C - > B, si se usa Bfs, se produce un error.

el algoritmo de Dijkstra

Alcance: sólo es aplicable a grafo ponderado no negativo .
1. Desde el punto de inicio S, S 0 punto, el punto del infinito positivo resto.
2. Actualizar S puntos adyacentes haciendo un 7, B 5, y marcar el punto S.
B. 5 3. El punto de actualización mínimo adyacente al punto B, la C 6 y puntos etiquetados
4. El punto A 7, C el punto 6, C es el punto mínimo, el punto A es 0 actualizaciones, y marcar el punto C, las marcas de punto A los extremos último algoritmo.
Encontrado en este momento, S punto más corta al punto B debe ser la S -> A -> C-> B, ruta 2, en lugar de cinco.
Aquí Insertar imagen Descripción

el algoritmo de Dijkstra para alcanzar las listas de adyacencia de

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1001;
const int M = 10001;
int  n ,m;
struct edge
{
	int v , w , next;   //v是连向顶点的编号,w是边的权重,next表示这条边的下一条边的编号 
	edge(){}
	edge(int _v , int _w , int _next)//结构体里的构造函数 
	{
		v = _v;
		w = _w;
		next = _next;
	}
}e[M*2];  //e存放的每一条边 

int head[N] , size;

void init()
{
	memset(head , -1 , sizeof(head));
	size = 0;
}

void insert(int u , int v ,int w)
{
	e[size] = edge(v , w , head[u]);  //head[u]当前u连出的第一条边 
	head[u] = size++;
} 

void insert2(int u , int v , int w)
{
	insert(u , v , w);
	insert(v , u , w);
}

int dis[N]; //原点到每一个点的最短路径 
bool vis[N]; //点是否被标记过 
void dijkstra(int u)
{
	memset(vis , false , sizeof(vis));     
	memset(dis , 0x3f , sizeof(dis));      //dis初始化为正无穷 
	dis[u] = 0;                            
	for(int i = 0 ; i < n ; i++)           //找n次没有标记过的点 
	{
		int mind = 10000000000 ,  minj = -1;
		for(int j = 1 ; j <= n ;j++)
		{
			if(!vis[j] && dis[j] < mind)    //如果点没有被标记且j位置路径小于最小值 ,则更新 
			{
				minj = j;
				mind = dis[j];
			}
		}
		if(minj == -1)  return;   //没有找到标记的点,不是连通图,返回 
		vis[minj] = true;
		for(int j = head[minj] ; ~j ; j = e[j].next)  // j != -1   遍历minj出发的每条边 
		{
			int v = e[j].v;
			int w = e[j].w;
			if(!vis[v] && dis[v] > dis[minj] + w)
			{
				dis[v] = dis[minj] + w;
			}
		}
	} 
} 

int main()
{
	init();
	int u , v ,w;
	cin >> n ;   //求1->n中的最短路,m是输入数据行数 
	for(int i = 2 ; i <= n ; i++)
	{
		for(int j = 1 ; j < i ; j++)
		{
			cin >> w;
			insert2(i , j , w);
		}
	}
	dijkstra(1);
	cout << dis[n] << endl; 
	return 0 ;
}

Montón lograr la optimización del algoritmo de Dijkstra

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int N = 1001;
const int M = 10001;
int  n ,m;
struct edge
{
	int v , w , next;   //v是连向顶点的编号,w是边的权重,next表示这条边的下一条边的编号 
	edge(){}
	edge(int _v , int _w , int _next)//结构体里的构造函数 
	{
		v = _v;
		w = _w;
		next = _next;
	}
}e[M*2];  //e存放的每一条边

struct Node{
	int v , d;
	Node(int v , int d):v(v) , d(d){}
	bool operator < (const Node &w)const{
		return d > w.d;
	}
};

int head[N] , size;

void init()
{
	memset(head , -1 , sizeof(head));
	size = 0;
}

void insert(int u , int v ,int w)
{
	e[size] = edge(v , w , head[u]);  //head[u]当前u连出的第一条边 
	head[u] = size++;
} 

void insert2(int u , int v , int w)
{
	insert(u , v , w);
	insert(v , u , w);
}
int d[N];
bool vis[N]; //点是否被标记过 
void dijkstra(int u)
{
	//memset(vis , false , sizeof(vis));     
	memset(d , 0x3f , sizeof(d));      //dis初始化为正无穷 
	d[u] = 0;
	priority_queue<Node> q;
	q.push(Node(u , 0));
	while(!q.empty())
	{
		u = q.top().v;
		q.pop();
		if(vis[u])  continue;
			for(int j = head[u] ; ~j ; j = e[j].next)  // j != -1   遍历minj出发的每条边 
		{
			int v = e[j].v;
			int w = e[j].w;
			if(!vis[v] && d[v] > d[u] + w)
			{
				d[v] = d[u] + w;
				q.push(Node(v , d[v]));
			}
		}
	}                           
} 

int main()
{
	init();
	int u , v ,w;
	cin >> n >> m;   //求1->n中的最短路,m是输入数据行数 
	while(m--)
	{
		cin >> u >> v >> w;
		insert2(u , v , w);
	}
	dijkstra(1);
	cout << d[n] << endl; 
	return 0 ;
}

SPFA algoritmo (figura calcula negativamente derecha)

Aquí Insertar imagen Descripción
No. 0 como punto de partida, 1,2,5 número enqueue, cola (125), No. 1 en este momento es 2; No. 2 es 5; III es infinito; 4 es infinito; No. 5 se 9
actualización de número de secuencia desencola 3,1, 3 en cola, la cola (253), No. 1 en este momento es 2; No. 2 es 5; III es 1; 4 es infinito; 9 No. 5 se
actualiza No. dequeue 4,2, 4 en cola, la cola (534), entonces

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e3 +9;
const int M = 1e4 +9;
const int inf = 0x3f3f3f3f;
int dis[N] , in[N];
bool vis[N];
int n , m;
struct edge{
	int v , w , next;
	edge(){}
	edge(int _v , int _w ,int _next)
	{
		v = _v;
		w = _w;
		next = _next;
	} 
}e[M << 1];  //M*2

int head[N] , len;
void init()
{
	memset(head , -1 , sizeof(head));
	len = 0;
}

void add(int u , int v ,int w)
{
	e[len] = edge(v , w , head[u]);
	head[u] = len++;
}

void add2(int u , int v ,int w)
{
	add(u , v , w);
	add(v , u , w);
}

/*bool*/void spfa(int u)
{
	memset(vis , false , sizeof(vis));
	vis[u] = true;
	memset(dis , 0x3f , sizeof(dis));
	dis[u] = 0;
	//memset(in , 0 ,sizeof(in)); in[u] = 1;
	queue<int> q;
	q.push(u);
	while(!q.empty())
	{
		u = q.front();
		q.pop();
		vis[u] = false;
		for(int j = head[u] ; ~j ; j = e[j].next)
		{
			int v = e[j].v;
			int w = e[j].w;
			if(dis[v] > dis[u] + w)
			{
				dis[v] = dis[u] + w;
				if(!vis[v])
				{
					q.push(v);
					vis[v] = true;
					//++in[v]; if(in[v] > n) return true;  
				}
			}
		}
	}
	//return false;
}

int main()
{
	init();
	int u , v , w;
	cin >> n >> m;
	while(m--)
	{
		cin >> u >> v >> w;
		add2(u , v , w); 
	} 
	spfa(1);
	cout << dis[u] << endl;
	/*if(spfa(1))  //判断是否有负环 
	{
		cout << "Yes" << endl;
	}else 
	cout << "No" << endl;
	*/ 
	return 0;
}

Múltiples fuentes más corto algoritmo de ruta

El camino más corto entre dos puntos

algoritmo de Floyd (sin la tabla adyacente derecho negativo del lado no se puede utilizar)

Pensamos que el uso del algoritmo de programación dinámica para calcular el camino más corto entre dos vértices dado en un grafo ponderado.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N =  205, inf = 0x3f3f3f3f;
int  g[N][N] , n , m;

void floyd(){
	for(int k = 0 ; k <= n ; k++)
	{
		for(int i = 0 ; i <= n ; i++)
		{
			for(int j = 0 ; j <= n ; j++)
			{
				g[i][j] = min(g[i][j] , g[i][k] + g[k][j]);
			}
		}
	}
}

int main()
{
	while(cin >> n >> m)
	{
		memset(g , 0x3f , sizeof(g));//floyd算法起手需要所有点为正无穷,自身点到自身距离为0
		for(int i = 1 ; i <= N; i++)
		{
			g[i][i] = 0;
		}
		int u , v , w ,s ,t;
		while(m--)
		{
			cin >> u >> v >> w;
			u++,v++;
			g[u][v] = g[v][u] = min(g[u][v] , w); //自己到自己的距离应该为0 
		}
		floyd();
		cin >> s >> t;
		s++,t++;
		if(g[s][t] > inf/2)  cout << "-1" << endl;    //判断是否有从起点到终点的路线 
		else cout << g[s][t] <<endl; 
	}
	return 0;
}
//HDU1874
Publicado 12 artículos originales · ganado elogios 0 · Vistas 111

Supongo que te gusta

Origin blog.csdn.net/qq_45244489/article/details/103921658
Recomendado
Clasificación