folyd思想(动归,可以包含负权值的边,但不能有负环):
将图G中顶点编号,从1到n。现在考虑从i到j的最短路径,若k是这条路上的中间结点,那么由i到k和由k到j的这两条子路径应分别是由i到k和由k到j的最短路径。否则,这条由i到j的路径就不是具有最小长度的路径。于是,最优性原理成立,这表明有使用动态规划的可能性。如果k是编号最高的中间结点,那么由i到k的这条路径上就不会有比k-1更大的结点通过。同样,由k到j路径上也不会有比k-1更大的结点通过。因此,可以把求取一条由i到j的最短路径看成如下过程:首先需要决策哪一个结点是该路径上具有最大编号的中间结点k,然后就再去求由i到k和由k到j这两对结点间的最短路径。当然,这两条路径都不可能有比k-1还大的中间结点。
则得到递推式:
A(i,j)k = min{A(i,j)k-1 , A(i,k)k-1 + A(k,j)k-1)}, k>=1
具体参看poj1603题:
题意如下:给出一个图,求图中两点之间的最短路径长度;
不说了直接看代码:
#include<iostream>
using namespace std;
const int Max = 21;
int main()
{
int map[Max][Max];
int t=1,n,m,k,i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=1; i<=20; i++)
for(j=1; j<=20; j++)
map[i][j] = 19;
while(n--)
{
cin >> m;
map[1][m] = 1;
map[m][1] = 1;
}
for(i=2; i<20; i++)
{
cin >> n;
while(n--)
{
cin >> m;
map[i][m] = 1;
map[m][i] = 1;
}
}
for(k=1; k<=20; k++) // Floyd算法核心代码。
for(i=1; i<=20; i++)
for(j=1; j<=20; j++)
if(map[i][k] + map[k][j] < map[i][j])
map[i][j] = map[i][k] + map[k][j];
cin >> n;
cout << "Test Set #" << t++ << endl;
while(n--)
{
cin >> i >> j;
cout << i << " to " << j << ": " << map[i][j] << endl;
}
cout << endl; // 输出格式要注意。
}
return 0;
}
最短路径求法未完待续……