【图论-最短路【1】】——floyed

图论也是信息学里面也是十分重要的一块内容,必须好好学习
                                                           ——题记

今天我要说的是图论中求最短路的一种方法——floyed

floyed算法可以说是所有图论里的算法里面最简单最稳定的算法了—主要代码只有五行最多,时间复杂度也是稳定三方,不需多解释,范围超过800就放弃吧!~!~


那么floyed的大致思路是这样的:

      先确定两个点,即起点和终点,在枚举中间点,比较通过这个点到达终点的距离和之间有起点到达终点的距离,取较小值其实这样可以构成一个三角形(自己脑补或者画图吧),本来根据两边之和大于第三边的三角形性质可以判定这种方法不行,但有时候有些点会是违背三角形原理的,那么这时候就会有最短路的产生、


代码结构如下:

   

for (int k=1;k<=n;k++)
  for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++)
       dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);


那么例题方一道:

    集合的点(原来的题目是啥忘了。有所改变。)

       题意描述:图G是一个无向连通图,没有自环,并且两点之间至多只有一条边。我们定义顶点v,u最短路径就是从v到u经过边最少的路径。所有包含在v-u的最短路径上的顶点被称为v-u的Geodetic顶点,这些顶点的集合记作I(v, u)。

               给你(x,y),请求出l(x,y) 

        题目分析:先理顺一下题意:以x为起点,y为终点,在以k为中间点,之间的路程要最短,那么k是符合要求的。不过如果预先不处理,最短路是很难求的。所以我们要先求一遍floyed,稳定O^3不会炸,然后再逐个枚举k点即可。

      那么具体代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,k,dis[5001],len[2001][2001],a[5001],s;
void floyed(){
    for (int k=1;k<=n;k++)
      for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
          if (len[i][k]+len[k][j]<len[i][j]){
            len[i][j]=len[i][k]+len[k][j];
        }
}//简单的floyed
int main(){
    memset(len,10,sizeof(len));
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        len[x][y]=len[y][x]=1;
    }//点与点之间的权值为1
    floyed();//预处理
    scanf("%d",&k);
    for (int i=1;i<=k;i++){
        s=0;
        scanf("%d%d",&x,&y);
        a[++s]=x;
        for (int j=1;j<=n;j++)
          if (len[x][j]+len[j][y]==len[x][y])
            a[++s]=j;//如果是最短路,就存入数组
        a[++s]=y;
        sort(a+1,a+s+1);//其实排序并没有什么软用
        for (int j=1;j<=s-1;j++) printf("%d ",a[j]);//输出
        printf("%d\n",a[s]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/huang_ke_hai/article/details/80190400