图论也是信息学里面也是十分重要的一块内容,必须好好学习
——题记
今天我要说的是图论中求最短路的一种方法——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; }