Training _ algorithm shortest path problem

Graph Theory algorithm training _ the shortest path algorithm

Here Insert Picture Description

Single-source shortest path problem

BFS algorithm is unable to solve the weighted graph shortest path problem, below
Here Insert Picture Description
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.
Here Insert Picture Description

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)

Here Insert Picture Description
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
Published 12 original articles · won praise 0 · Views 111

Guess you like

Origin blog.csdn.net/qq_45244489/article/details/103921658