最短路径算法(1)

最短路径算法(1)

最短路算法(1)

介绍floyd:

用于求全源最短路径的算法,这个代码非常简短好记,这里会记录两种应用。

1.简单模板优化以及处理连通性问题

这个算法可以用来求传递闭包(注释中有)。

代码如下:

const int N = 100+50;

const int INF = 500;//这个不可以太大,如果太大,那么D[i][k]+D[k][j]可能会溢出

int D[N][N];

void floyd(int n){

for(int k = 1;k <= n;k++)

for(int i = 1;i <= n;i++)

//if(G[i][k]!=INF) 一个优化加速

for(int j = 1;j <= n;j++)

D[i][j] = min(D[i][j],D[i][k]+D[k][j]);//这个可以优化加速

//对于连通性的题目,把数值变成o和1来表示联通与否

//如果把上一句话变成D[i][j] = D[i][j]||(D[i][k]&&D[k][j]),就可以用来求传递闭包

cout<

}

D数组的解释:

从i号顶点到j号顶点只经过前k号点的最短路程。

事实上,D数组本来应该是f[k][x][y],这表示为:

经过前k个点从x到y的最短路径

这个数组的解法是:

D[k][x][y] = min(D[k-1][x][y],D[k-1][x][k]+D[k-1][k][y]);

也就是经过k是否可以让x,y更短

这是我们发现,若删掉第一维不影响结果,也就是说第一维是无意义的。

得到状态转移方程:

D[x][y] = min(D[x][y],D[x][k]+D[k][y]);

2.最小环

现在我们看一个应用:

利用floyd求解最小环问题:

假设有n个顶点,m条边,如何求解在一个图中权值和最小的环?

先考虑暴力解法:

在删掉u的每一条邻边(u,v),在计算u到v的最短路,再加上原来的(u,v),这样得到一条最小环。这需要枚举m条边,求最短路的时间复杂度可以优化到(n+m)logn ,这样整体的时间复杂度就是O (m(n+m)logn)。

使用floyd算法是可以解决这个问题的:

floyd有这样一个性质:

在最外层循环到点 k 时(尚未开始第 k 次循环),最短路数组 D 中,D[u][v] 表示的是从 u到v且仅经过编号在 [1,k) 区间中的点的最短路。

那么对于最短路(u,v),最小环就应该是dis[u][v]加上另外的一个点,记作w。

对于(u,v)来说状态方程就是:

ans = min(ans,dis[u][v] + weight[u][w]+weight[w][v])

代码如下:

for(int k = 1;k < = n;k++){

for(int i = 1;i <= k;i++)

for(int j = 1;j <= k;j++)

ans = min(ans,dis[u][v] + weight[u][w]+weight[w][v]);

for(int i = 1;i <= n;i++)

for(int j = 1;j <= n;j++)

dis[i][j] = dis[i][k]+dis[k][j];

}

相关数据

价值的意思
beat365倍率

价值的意思

📅 09-24 👁️ 7604
世界杯的中国元素(除了球队)|财料
beat365中国

世界杯的中国元素(除了球队)|财料

📅 07-11 👁️ 8260
如何剪切 MP4 视频
beat365中国

如何剪切 MP4 视频

📅 01-23 👁️ 5644