最短路 (Floyd & Dijkstra)(咕咕咕,未完(因机房关门)待续)

前言

最短路需要用到图论的知识
图论基础知识@jmy orz

今天我们学习了Floyd 和 Dijkstra。笔者本着总结了记得总会牢一点的精神写下了本篇blog。

Floyd

什么是Floyd呢?问问度娘吧

Floyd 和 区间DP 有点像,动态规划点集大小为区间。

代码
#include 
#include 
#include 
#include 
using namespace std;

int n, m;
int dp[105][105];
int pre[105][105];
int main() {
	scanf("%d %d", &n, &m);
	int x = 0, y = 0;
	memset(dp, 0x3f, sizeof(dp));
	for(int i = 1; i<= n; i ++){
		dp[i][i] = 0;
	}
	int m;
	for(int i = 1; i <= m; i ++){
		int x, y;
		scanf("%d %d", &x, &y);
		dp[x][y] = 1;
 	}
	for(int k = 1; k <= n; k ++){
		for(int i = 1; i <= n; i ++){
			for(int j = 1; j <= n; j ++){
				if((dp[i][k] + dp[k][j]) < dp[i][j]){
					dp[i][j] = dp[i][k] + dp[k][j];
				}
			}
		}
	}
	int s, t;
	scanf("%d %d", &s, &t);
	if(dp[s][t] = 0x3f){
		printf("no solution\n");
	}
	else{
		printf("%d", dp[s][t]);
	}
	return 0;
} 

从上述代码中我们就可以显而易见的发现,Floyd有一个致命的弱点就是它的时间复杂度 O ( n 3 ) O(n^3) O(n3) 但是它也有很多优点呀!比如它可以实现负权的情况,同时它可以多点查询

但我们要输出最短路径该怎么做呢?

用递归实现就好了,每一位保存其对应的前一位的位置

#include 
#include 
using namespace std;
int n, m;
int dp[505][505];
int pre[505][505];
int flag1, flag2;
void print(int x){
	if(pre[flag1][x] == 0){
		return;
	}
	print(pre[flag1][x]);
	printf(" %d", x);
}
int main() {
	memset(dp, 0x3f, sizeof(dp));
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i ++){
		dp[i][i] = 0;
	}
	for(int i = 1; i <= m; i ++){
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		dp[a][b] = c;
		pre[a][b] = a;
	}
	for(int k = 1; k <= n; k ++){
		for(int i = 1; i <= n; i ++){
			for(int j = 1; j <= n; j ++){
				if(dp[i][j] > dp[i][k] + dp[k][j]){
					dp[i][j] = dp[i][k] + dp[k][j];
					pre[i][j] = pre[k][j];
				}
			}
		}
	}
	scanf("%d %d", &flag1, &flag2);
	printf("%d\n", dp[flag1][flag2]);
	printf("%d", flag1);
	print(flag2);
	return 0;
}

Dijkstra

有啥不会问度娘

思想

运用贪心的思想,不断的找出未被标记且离s最近的点,并运用松弛的思想,改变运用该点松弛的值,在遍历完成后,输出结果。

证明(非严格,不详细)

因为每一个输出时, 它已经成为了未被标记且离s最近的点,在剩下的其余点中,无论如何都不可能短于它,也就不可能构成其的最短路,而在前面已被输出的数中能连接的都进行了判断,不能连接的。。。
所以当每个点都被标注时都成为了其最短路。(我哔哔了些啥???)

咕咕咕

咕咕咕

咕咕咕

咕咕咕

咕咕咕

你可能感兴趣的:(图论)