poj1125 Floyd-Warshall算法

来源:互联网 发布:华为交换机端口应用acl 编辑:程序博客网 时间:2024/05/01 17:22

Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。我们平时所见的Floyd算法的一般形式如下:

1 void Floyd(){
2     int i,j,k;
3     for(k=1;k<=n;k++)
4         for(i=1;i<=n;i++)
5             for(j=1;j<=n;j++)
6                 if(dist[i][k]+dist[k][j]<dist[i][j])
7                     dist[i][j]=dist[i][k]+dist[k][j];
8 }

  注意下第6行这个地方,如果dist[i][k]或者dist[k][j]不存在,程序中用一个很大的数代替。最好写成if(dist[i][k]!=INF && dist[k][j]!=INF && dist[i][k]+dist[k][j]<dist[i][j]),从而防止溢出所造成的错误。
  上面这个形式的算法其实是Floyd算法的精简版,而真正的Floyd算法是一种基于DP(Dynamic Programming)的最短路径算法。
  设图G中n 个顶点的编号为1到n。令c [i, j, k]表示从i 到j 的最短路径的长度,其中k 表示该路径中的最大顶点,也就是说c[i,j,k]这条最短路径所通过的中间顶点最大不超过k。因此,如果G中包含边<i, j>,则c[i, j, 0] =边<i, j> 的长度;若i= j ,则c[i,j,0]=0;如果G中不包含边<i, j>,则c (i, j, 0)= +∞。c[i, j, n] 则是从i 到j 的最短路径的长度。
  对于任意的k>0,通过分析可以得到:中间顶点不超过k 的i 到j 的最短路径有两种可能:该路径含或不含中间顶点k。若不含,则该路径长度应为c[i, j, k-1],否则长度为 c[i, k, k-1] +c [k, j, k-1]。c[i, j, k]可取两者中的最小值。
  状态转移方程:c[i, j, k]=min{c[i, j, k-1], c [i, k, k-1]+c [k, j, k-1]},k>0。
  这样,问题便具有了最优子结构性质,可以用动态规划方法来求解。

 

  为了进一步理解,观察上面这个有向图:若k=0, 1, 2, 3,则c[1,3,k]= +∞;c[1,3,4]= 28;若k = 5, 6, 7,则c [1,3,k] = 10;若k=8, 9, 10,则c[1,3,k] = 9。因此1到3的最短路径长度为9。

 


 对于1125,这道题目的思路是求出某一点到所有点的最小值,然后在在这些最小路径中求出最大的值,再在这些最大值中找到一个最小值点

#include<iostream>
using namespace std;
int ls[110][110];
int main()
{
 int maxx,pos,i,j,k,n,p,num,c;
 while(cin>>n)
 {
  if(n==0)
    break;
   for(i=1;i<=n;i++)
   for(j=1;j<=n;j++)
    ls[i][j]=1000000;
  for(i=1;i<=n;i++)
  { 
   cin>>p;
   for(j=1;j<=p;j++)
   {
    cin>>num>>c;
    ls[i][num]=c;
   }
  }
  for(k=1;k<=n;k++)//注意,此处的k循环一定要在最外层
 for(i=1;i<=n;i++)
   for(j=1;j<=n;j++)

  {
   if(ls[i][j]>ls[i][k]+ls[k][j])
    ls[i][j]=ls[i][k]+ls[k][j];
  }
  int t=1000000;
  pos=-1;
  for(i=1;i<=n;i++)
  {
   maxx=0;
   ls[i][i]=0;
   for(j=1;j<=n;j++)
   {
    
                 if(ls[i][j]>maxx)
     {
      maxx=ls[i][j];
    
     }

   }
   if(maxx<t)
   {t=maxx;pos=i;}
  }
  if(t==1000000)
   cout<<"disjoint"<<endl;
  else
   cout<<pos<<" "<<t<<endl;
 }
 return 0;
}