poj 1603

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;
}

 

最短路径求法未完待续……

你可能感兴趣的:(poj)