算法思路:用中间点 𝑘 更新最短路, 𝑖 → 𝑘 → 𝑗 。
一步就是连接 𝑖 → 𝑘, 𝑘 → 𝑗,然后进一步细分……
代码部分
memset(dst, 0x3f, sizeof dst);
for (int i = 1, u, v, w; i <= m; ++i)
{
scanf("%d%d", &u, &v);
scanf("%d", &dst[u][v]);
dst[v][u] = dst[u][v];
}
for (int i = 1; i <= n; ++i) dst[i][i] = 0;
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
dst[i][j] = std::min(dst[i][j], dst[i][k] + dst[k][j]);
来到例题吧
问题 A: 【一本通图 最短路径算法】最短路径问题
[题目描述]
平面上有n个点(n<=100),每个点的坐标均在-10000到10000之间.其中的一些点之间有连线.若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离.现在的任务是找出从一点到另一点之间的最短路径.
输入
共n+m+3行
第一行为整数n.
第2行到第n+行,每行两个整数x和y,描述了一个点的坐标(以一个空格分开)
第n+2行为一个整数m,表示图中连线的个数.
以后的m行,每行描述一条连线,由两个整数i和j组成,表示第i个点和第j个点之间有连线.
最后一行;两个整数s和t,分别表示源点和目标点.
输出
仅一行,一个实数(保留两位小数),表示从s到t的最短路径长度
样例输入
5 0 0 2 0 2 2 0 2 3 1 5 1 2 1 3 1 4 2 5 3 5 1 5
样例输出
3.41
思路:这道题只需要用邻接矩阵就能轻松搞定。ljjz[i][j]表示i到j的最短路径 ,不断更新就可以解决了。zb数组表示坐标。附上代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, x, y, s, t;
int zb[101][3];
double ljjz[101][101];
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &x, &y);
zb[i][1] = x;
zb[i][2] = y;
}
memset(ljjz, 0x7f7f7f, sizeof(ljjz));
scanf("%d", &m);
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
ljjz[x][y] = ljjz[y][x] = sqrt(pow(double(zb[x][1] - zb[y][1]), 2) +
pow(double(zb[x][2] - zb[y][2]), 2));
}
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) && (ljjz[i][j] > ljjz[i][k] + ljjz[k][j]))
ljjz[i][j] = ljjz[i][k] + ljjz[k][j];
}
}
}
scanf("%d%d", &s, &t);
printf("%.2lf\n", ljjz[s][t]);
return 0;
}
还有例题
问题 C: 【一本通图 最短路径算法】最小花费
[题目描述]
在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。
输入
第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。
1<=n<=2000
输出
输出A使得B到账100元最少需要的总费用。精确到小数点后8位。
样例输入
3 3 1 2 1 2 3 2 1 3 3 1 3
样例输出
103.07153164
话不多说,直接附上代码:
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
int n, m, x, y, z, a, b;
double ljjz[2001][2001];
double c[2001];
bool vis[2001];
void dijkstra()
{
c[a] = 1;
for(int i = 1; i <= n; i++)
{
int k = -1;
for (int j = 1; j <= n; j++)
{
if (!vis[j] && c[k] < c[j])
k = j;
}
vis[k] = true;
for(int j = 1; j <= n; j++)
c[j] = max(c[j], c[k] * ljjz[k][j]);
}
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i++)
{
cin >> x >> y >> z;
double t = (100.0 - (int)z) / 100;
ljjz[x][y] = ljjz[y][x] = max(ljjz[x][y], t);
}
cin >> a >> b;
dijkstra();
printf("%.8lf\n", 100.0 / c[b]);
//cout << c[b] << endl;
return 0;
}
看懂了这些你就明白了floyd算法,不过不得不承认他是万能的,不过他非常耗时,时间复杂度为O(n^3), 仔细看好数据范围再用Floyd。