Floyd的变形大概分为三种情况,通过“或”,max,min运算的变形。这篇文章只粗略介绍后两种情况。
如图:
最大的最小边权值
从1到7的最大的最小边权值是25,即1->2->4->7。
如 POJ 2663,关于这道题目,我们可以抽象一下,即在保证货车不超过道路给定的最小限重量的情况下,使得货车装载的货物的重量最大。
即该边是一个顶点到另一个顶点所有路径中的最小的。
既然模型抽象出来了怎么去求解呢?这时我们可以想到Floyd的原理,即采用递推的方式计算A(k)[i][j],增加顶点Vk作为中间顶点之后比较i->j与i->k>j比较,然后进行变形。其实这也是一种动态规划的思想。(具体的去参考Floyd算法原理)
归纳一下求解的代码:
1、最大的最小边权值:这条边的权值是它属于的这条路径中最小的,但在所有从s->t的路径中它是最大的。
/*预处理*/ void init() { for(int i = 1; i < MAXN; i++) // <= MAXN 又一次越界了。 { for(int j = 1; j < MAXN; j++) { d[i][j] = (i == j) ? INF : 0; } } } /*Floyd*/ void Floyd() { for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) d[i][j] = max(d[i][j], min(d[i][k], d[k][j])); }
2、最小的最大边权值:这条边的权值是它属于的这条路径中最大的,但在所有从s->t的路径中它是最小的。
从A到G有很多条不同的路径,但是A->G最大边权值是80,即A->C->F->D->G。
/*预处理*/ void init() { for(int i = 1; i < MAXN; i++) { for(int j = 1; j < MAXN; j++) { d[i][j] = (i == j) ? INF : 0; } } } /*Floyd*/ void Floyd() { for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) d[i][j] = max(d[i][j], min(d[i][k], d[k][j])); //d[i][j] = min(d[i][j], max(d[i][k], d[k][j])); }
练习参考题: UVA 10048、 UVA 10099