[导读]给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。
注意:看这篇随笔之前请先看之前写的《最短路径之迪杰特斯拉算法》。在上一篇随笔中,我们了解到了迪杰特斯拉算法,不知道大家发现了没有,该算法算的是单源路径,也就是已经确定好了所求最短路径的起点城市,因此我们只使用了一维数组p[i],T[i],其实,这已经默认了是P[1][i]和T[1][i],也就是从一号城市到其他城市的最短路径,但是在现实生活中,我们可不只是只需要找某一个特定的城市到其他城市的最短距离,我们往往会需要查找从不同的城市到其他城市的最短路径,这也就是多源最短路径问题,需要用到的是我们今天要讲到的弗洛伊德算法,这时,一维数组就不够用了,我们则需要二维数组,相信聪明的你已经看出来了,我们只需要在迪杰特斯拉算法中多加一层循环,数组多一个维度,就可以求出以不同的城市为起点到其他城市的最短路径了~下面附上样例题目和代码:
题目描述:
给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。
输入秒描述:
给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。
输出描述:
输出Q行,每行一个整数表示询问的答案
输入样例:
9 10 2
1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 9
5 7
输出样例:
5
6
代码:
#include
#define INF 999
int min(int a,int b)
{
return a < b ? a: b;
}
int main(void)
{
int n,m,v,u,w,q,p[21][21],l[7][7],T[21][21],i,j,k,flag,flag2[21][21] = {0},min1 = -1;
scanf ("%d%d%d",&n,&m,&q);
for (i = 1; i <= m;i++)
{
scanf ("%d%d%d",&v,&u,&w);
l[v][u] = w;
l[u][v] = w;
flag2[v][u] = 1;
flag2[u][v] = 1;
}
for (i = 1;i <= n;i++)
{
p[i][i] = 0;
}
for (i = 1;i <= n;i++)
{
for (j = 1;j <= n;j++)
{
if(j != i)
T[i][j] = INF;
}
}
for (k = 1;k <= n;k++)//这层循环代表以不同的城市为起点
{
for (i = 1;i <= n;i++)
{
if(i != k)
{
for (j = 1;j < i;j++)
{
if(flag2[j][i])
{
T[k][i] = min(T[k][i],p[k][j] + l[j][i]);//求出临时最短路径
}
}
for (j = i;j <= n;j++)
{
if(j != k)
{
if(min1 == -1 || min1 > T[k][j])
{
min1 = T[k][j];
flag = j;
}
}
}
p[k][flag] = min1;//求出最短路径
min1 = -1;
}
}
//第一层大循环只是求得了从标号小的城市到标号大的城市的最短路径,因此还需要第二次大循环来求得真正的最短路径
for (i = 1;i <= n;i++)
{
if(k != i)
{
for (j = 1;j <= n;j++)
{
if(flag2[j][i])
{
p[k][i] = min(p[k][i],p[k][j] + l[j][i]);
}
}
}
printf ("%d->%d = %d
",k,i,p[k][i]);
}
}
for (i = 1; i <= q;i++)
{
scanf ("%d%d",&v,&u);
printf ("%d
",p[v][u]);
}
return 0;
}