蓝桥杯day13——最短路Floyd算法

概述

  1. 简介:
    Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。

  2. 算法过程:
    1,从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。

    2,对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
    把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i][j]=d,d表示该路的长度;否则G[i][j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i][j]表示从Vi到Vj需要经过的点,初始化D[i][j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i][j] = min( G[i][j], G[i][k]+G[k][j] ),如果G[i][j]的值变小,则D[i][j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
    比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。

  3. 状态转移方程
    其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]};
    map[i,j]表示i到j的最短距离,K是穷举i,j的断点,map[n,n]初值应该为0,或者按照题目意思来做。
    当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路。

例题

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,边权可能为负数。

再给定 k 个询问,每个询问包含两个整数 x 和 y,表示查询从点 x 到点 y 的最短距离,如果路径不存在,则输出 impossible。

数据保证图中不存在负权回路。

输入格式
第一行包含三个整数 n,m,k。

接下来 m 行,每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。

接下来 k 行,每行包含两个整数 x,y,表示询问点 x 到点 y 的最短距离。

输出格式
共 k 行,每行输出一个整数,表示询问的结果,若询问两点间不存在路径,则输出 impossible。

数据范围
1≤n≤200,
1≤k≤n2
1≤m≤20000,
图中涉及边长绝对值均不超过 10000。

输入样例:
3 3 2
1 2 1
2 3 2
1 3 1
2 1
1 3
输出样例:
impossible
1
难度:简单
时/空限制:1s / 64MB

N = 210
INF = 1000010

d = [[INF] * N for _ in range(N)]

for i in range(N) :
	d[i][i] = 0

def floyd() :
	for k in range(1, n + 1) :
		for i in range(1, n + 1) :
			for j in range(1, n + 1) :
				d[i][j] = min(d[i][j], d[i][k] + d[k][j])

n, m, k = map(int, input().split())

for i in range(m) :
	x, y, z = map(int, input().split())
	d[x][y] = min(d[x][y], z)
floyd()
for i in range(k) :
	x, y = map(int, input().split())
	if d[x][y] >= INF // 2 :
		print("impossible")
	else : print(d[x][y])

因为d[x][y]可能被在中途被松弛,所以需要d[x][y] >= INF // 2,Bellman—Ford算法同理
对于重边,取最小值

总结

图论最短路模块以Floyd这一简单的算法轻松结尾,多练!!!

posted @   chanxe  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示