每个点与点之间的瓶颈路
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];
// 两个节点同时向上走 , 直到两个节点相同时
这个题目最普通的算法就是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];
// 两个节点同时向上走 , 直到两个节点相同时
相关文章推荐
- LA 5713 Qin&nbsp…
- uva 11354 Bond
- 最小生成树的一些性质和理解
- poj 2485 简单的最小生…
- 我的博客今天0岁42天了,我领取了…
- LA 4080 Warfare A…
- hdu 2433 最短路树
- 【快速】排序, T(n) = O(nlgn),O(n^2) S(n) = O(lgn) --- 不稳定
- (C# 基础) 类访问修饰符
- LA 3713 Astronauts
- LA 3211 Now or later
- uva 11324
- LA 5135 Mining Your Own Business
- http://kb.cnblogs.com/page/130970/ -http协议
- poj 2942 LA3523 点-双…
- uva 10047
- STL中优先队列的用法
- 并查集及其路径的压缩
- 求欧拉回路的路径 dfs的一种新运用
- poj 2676