Graph Theory algorithm training _ the shortest path algorithm
Single-source shortest path problem
BFS algorithm is unable to solve the weighted graph shortest path problem, below
S to B should be single-source shortest S -> A -> C - > B, if used Bfs, an error occurs.
Dijkstra's algorithm
Scope: only applicable to non-negative weighted graph .
1. From the start point S, S 0 point, the rest point of positive infinity.
2. Update S adjacent dots making A 7, B 5, and mark the point S.
5 3. The minimum update point adjacent to the point B, the C 6 and points labeled B.
4. The point A 7, C point 6, C is the minimum point, point A is 0 updates, and mark the point C, the point A marks the last algorithm ends.
Found at this time, S shortest point to point B should be the S -> A -> C-> B, path 2, instead of five.
Dijkstra's algorithm to achieve the adjacency lists of
#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 ;
}
Heap achieve optimization of Dijkstra's algorithm
#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 algorithm (FIG calculated negatively right)
No. 0 as a starting point, 1,2,5 enqueue number, queue (125), No. 1 at this time is 2; No. 2 is 5; III is infinite; 4 is infinite; No. 5 is 9
update sequence number dequeuing 3,1, 3 enqueued, the queue (253), No. 1 at this time is 2; No. 2 is 5; III is 1; 4 is infinite; 9 No. 5 is
updated No. dequeue 4,2, 4 enqueued, the queue (534), then
#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;
}
Multi-source shortest path algorithm
The shortest path between any two points
Floyd algorithm (without the negative-side right adjacent table can not be used)
Thought the use of dynamic programming algorithm to calculate the shortest path between two given vertex in a weighted graph.
#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