原本只会用Floyd算法的板子,今天上数据结构,老师讲了下,有点深入理解了,打通了任通二脉。
作用 计算任意两点间的最短路径。
时间复杂度是O(N3)的。
设
D
k
[
i
,
j
]
D^k[i,j]
Dk[i,j]是经过结点标号数不超过k的结点从
i
i
i到
j
j
j的最短路径。
其实是从上一个状态(
D
k
−
1
[
i
,
j
]
D^{k-1}[i,j]
Dk−1[i,j]转移过来的)从经过结点标号数不超过k-1的结点从
i
i
i到
j
j
j的最短路径。转移过来的。
在原不超过
k
−
1
k-1
k−1的基础上加上标号为
k
k
k这个结点,判断是否路径变短了。
这样容易理解点吧。其实就是动态规划,要求不大于k的需要求出不大于k-1的。边界是不经过其他点,直接从i到j。结果就是不大于n的路径。
知道原理就能写出来代码:
int d[300][300],n,m;
int main() {
cin>>n>>m;///n个点,m个边
///无向边可以直接转成两个有向边
memset(d,0x3f,sizeof d);///初始化,让到不了的点赋成无穷
for(int i=1;i<=n;i++) d[i][i]=0;///对角线为零 ,防止出现环
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
d[x][y]=min(z,d[x][y]);
///d[y][x]=min(z,d[y][x]);///无向边
}
///求Floyd最短路
for(int k=1;k<=n;k++){///不超过结点k的[i,j]最短路径
for(int i=1;i<=n;i++){///第一个结点
for(int j=1;j<=n;j++){///第二个节点
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);///找到最短路径
}
}
}
///输出两点的最短路径。
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
printf("%d ",d[i][j]);///d[i][j]=0x3f表示到不了
printf("\n");
}