formación algoritmo de la teoría de grafos _ el algoritmo del camino más corto
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
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.
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)
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