今天学了floyd和dijkstra算法。
floyd算法基本思想:最刚开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转......允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。
代码实现如下:
#include<stdio.h>
#define inf 0x3f3f3f3f
int e[51][51];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j)e[i][j]=0;
else e[i][j]=inf;
}
}
int t1,t2,t3;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
e[t1][t2]=t3;
}
//核心代码
for(int i=1; i<=n; i++)//所被允许的中转点
for(int j=1; j<=n; j++)
for(int k=1; k<=n; k++)
if(e[j][k]>e[j][i]+e[i][k])
e[j][k]=e[j][i]+e[i][k];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",e[i][j]);
}
printf("\n");
}
return 0;
}
dijkstra算法基本思想:每次找到离源点最近的一个顶点,然后通过该顶点的所有出边来松弛源点到其余各顶点的路程(即扩展),被松弛过的的点需要被标记,以防下次被访问到。
代码实现如下:
//dijkstra算法
#include<stdio.h>
#define inf 0x3f3f3f3f
int e[10001][10001],dis[10001],book[10001];
int main()
{
int n,m,start;
scanf("%d%d%d",&n,&m,&start);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)e[i][j]=0;
else e[i][j]=inf;
}
}
int t1,t2,t3,u;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
e[t1][t2]=t3;
}
//初始化dis数组
for(int i=1;i<=n;i++)
{
dis[i]=e[start][i];
}
book[start]=1;
//核心代码
for(int i=1;i<=n-1;i++)//除源点外有n-1个点需要扩展
{
int min=inf;
for(int j=1;j<=n;j++)
{
if(book[j]==0&&dis[j]<min)
{
min=dis[j];
u=j;
}
}
book[u]=1;
for(int j=1;j<=n;j++)//更新与u相连点的dis[]
{
if(e[u][j]<inf)
{
if(dis[j]>dis[u]+e[u][j])
dis[j]=dis[u]+e[u][j];
}
}
}
for(int i=1;i<=n;i++)
{
printf("%d ",dis[i]);
}
return 0;
}
总结:floyd算法在代码上比较简单,也可以处理带有负权边的图(负权回路除外),但时间复杂度较高。dijkstra算法时间复杂度是N平方,但不可以处理带有负权边的图