您的位置:首页 > 其它

每个点与点之间的瓶颈路

2013-12-14 20:03 281 查看
瓶颈路:最小生成树中边权最大那条边 。

这个题目最普通的算法就是bfs和dfs , 但这旺旺都会超时 。

下面有两种各是时间效率或空间效率高的算法。

1、 时间高效率

   
当你要查询每对点与点之间的瓶颈路时 , 最好的方法时 , 先把所有点之间的求出来 , 然后存放到一个数组中 ,
但这要求节点数不能太大(如:n = 50000 , 就不可能全部存下来 , 只能一个一个求) 。

   
我们先把最小生成树看成是一颗有根树 , 并且找出一个根节点(任意) , 然后再从这个根节点开始遍历,求点与点之间的最大边权 。
怎么遍历呢?我们想到了dfs (经过优化的dfs) , 我们让节点至于被标记(已经被遍历的节点)的节点进行比较 ,
这样就不会使每对节点都要被比较两次 。

代码:

void dfs(int v)

{

    for ( int u
= 1; u <= n; ++u )  //这里还可以用邻接表来减少时间

    {

       
if(!done[u] && p[u] == v) 
//  done检查是否被标记 , p是指u是不是v的父亲节点

   
    {

          
done[u] = 1;

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

              
if (done[x] && x != u ) 

   
   
   
   {

   
   
   
   
   maxbian[x][u] = maxbian[u][x]

maxbian[x][v]>maxbian[u][v]?maxbian[x][v]:maxbian[u][v];

   
   
   
   }

          
dfs(u);

       
}

    }

}

2、空间高效率

    就像上面说的那样 ,
当不能存储所有节点之间的最大边权的情况下的算法 , 这个算法论单个求肯定高于上面那个算法 , 但要求所有点与点之间时 ,
就比上面那个算法更慢了。

   
这个算法充分的考虑的最小生成树是一颗树的性质 。 先把其建立成一颗有根树(根是任意的) ,
并记录每个节点在这个有根树中的深度、父亲节点 、 以及和父亲节点的距离 。

    当要求x , 和 y
,之间的最小瓶颈路时 , 先判断x、y的深度是不是一样的 , 如果不是 , 那就先使它们的深度一样, 当深度一样之后 ,
x、y再同时往根的方向走 , 直到x == y 时 。(在这里我们可以肯定判断出 , x、y的某个祖先一定是同一个节点 , 所有 ,
当x、y深度一样时 , 并同时向上遍历 , 那么它们就一定会同时到达这个祖先)

代码:

int solve(int x , int y)

{

    int m1 = -1
, m2 = -1;  // 
初始化两个节点在遍历过程中的最大边权

    if(f[x] >
f[y])   // 
当这两个节点深度不一样时

    {

   
   
while(f[x]>f[y])

   
    {

   
   
    if(m1 <
dist[x])  m1 = dist[x]; 
//  改变最大边权

   
   
    x = p[x];
//  向上走后的节点 , 也就是其父亲节点

   
    }

    }

    else if(f[x]
< f[y])

    {

   
    while(f[x]
< f[y])

   
    {

   
   
    if(m2 <
dist[y])  m2 = dist[y];

   
   
    y =
p[y];

   
    }

    }

    while(x !=
y)  //  这时 , 两个节点的深度已经一样了

    {

   
    if(m1 <
dist[x])  m1= dist[x]; 
//  两个节点同时向上走 , 直到两个节点相同时

   
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: