Floyed-Warshall【弗洛伊德算法】
Floyed-Warshall:适用于规模小的图,如果存在负权,需要判断负圈。
权值:类似于从节点 s 到 j 依次经过的长度之和。
类似动态规划:从 s 到 t 的过程程中我们考虑是走还是不走,然后取两者的最小权,最终 s 到 t 的
最小权值之和就是我们要求的最短路径。
做出如下类比:每个点看成一个灯,初始时每个灯都是熄灭状态,结点之间的权值初始化成无穷大。
然后依次计算出两个连通结点之间的距离,灯依次亮起,直到所有的灯光亮起,计算结束。
判断负圈:graph[ i ][ i ]是 i 到外面绕一圈回来的最小路径,if( graph[ i ][ i ] < 0 ) graph[ i ][ i ] = 0;
好处:避免陷入负圈中走不出来。
Floyed 采用三重循环, 复杂度 O(n³)
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if((i!=j)&&(i!=k)&&(j!=k)&&(f[i][k]+f[k][j]<f[i][j]))//松弛操作,使得f[i][j]是最短的
{
f[i][j]=f[i][k]+f[k][j];
}
}
}
}
题意:有 n 家店,每家店坐标是 x,y; 有 m 个连通条件, 问从 s 到 t 的最短路径是多少?
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e2 + 7;
int a[maxn][3];
double dis_map[maxn][maxn]; //邻接矩阵存图
int n,m,x,y,s,t; // s:起点 , t:终点 , n: 店数 , m: (m+1)家店数连通 , x 与 y 有通道
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin>>n;
for(int i = 1; i <= n; i++) //输入 n 家店的坐标
cin>>a[i][1]>>a[i][2];
cin>>m;
memset(dis_map,0x7f,sizeof(dis_map));//将这个矩阵初始化一下
for(int i = 1; i <= m; i++)
{
cin>>x>>y;
double dis = sqrt(pow(double(a[x][1]-a[y][1]),2)+pow(double(a[x][2]-a[y][2]),2)); //有通道的两家店的距离
dis_map[y][x] = dis_map[x][y] = dis; //权值
}
cin>>s>>t;
for(int k = 1; k <= n; k++)
{
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if((i!=j) && (i!=k) && (j!=k) && (dis_map[i][k]+dis_map[k][j] < dis_map[i][j])) //松弛,使 dis_map[i][j]最小
{
dis_map[i][j] = dis_map[i][k] + dis_map[k][j];
}
}
}
}
printf("%.2lf",dis_map[s][t]);
}

https://www.luogu.org/problem/P1744
永远年轻 永远热泪盈眶!

浙公网安备 33010602011771号