MST中求任意两点条路径上的最长边…
2013-12-14 20:06
267 查看
1、MST任意两点路径上的最长边
这其实是在求次小生成树 , 因为我们可以知道 ,
次小生成树和最小生成树之间只有一条边不一样 , 因此我们只需要枚举不在最小生成树中边 ,
同时我也要求出该两点在最小生成树中之间的路径中的最长边的值。
解法:我们用kruskal算法来求出最小生成树 , 对于kruskal算法 , 当我们要加入一条边时 , 实际上是在把两颗“树”合并
, 那么从这两颗树上各去除一个点 , 则这两点路径之间的最大边 , 就是当前加入的这条边,因此我们只需要记录每颗树就行了 ,
对于每颗树我们可以用邻接表(数组模拟)来存 。
代码:
int kruskal()
{
sort(edge ,
edge+m , cmp); //对边进行排序
int i , x ,
y , g , h , k = 0;
int sum =
0;
for(i = 0; i
< n; i++) //先把每个点都看成是一颗树
{
link[i].x =
i+1;
link[i].next
= head[i+1];
end[i+1] =
i;
head[i+1] =
i;
}
for(i = 0; ;
i++)
{
if(k ==
n-1) break;
x =
find(edge[i].x); // 判断这两个点是不是在同一颗树上
y =
find(edge[i].y);
if(x !=
y)
{
for(int w =
head[x]; w != -1 ; w = link[w].next)
{
for(int v =
head[y]; v != -1; v = link[v].next)
{
length[link[w].x][link[v].x] = length[link[v].x][link[w].x] =
edge[i].w;
}
}
link[end[x]].next = head[y];//两个树合并成一颗树
end[x] =
end[y];
p[y] = x;
//这是并查集的合并 , 但要和上面的合并相对应
k++;
sum +=
edge[i].w;
}
}
return
sum;
}
2、MST中任意两点路径上的最短边
解法:这和上面的解法差不多 。 也和上面一样 , 用kruskal算法 , 当成是两颗树的合并 。 我假设现在要加入u 、 v这条边
, 并且保证u 、 v不在同一颗树上 , 那么假设点 x 在u 的树上 、 点y在 v的树上 ,
现在我们要求x 、y路径上的最小边 , 如果x就u , y就是v , 那么它们之间的最短边就是u、v之间的权值 , 如果x不是u ,
y不是v , 那么就意味着在x、y的路径上 , 除了u、v这条边之外 , 还有其他的边 ,
并且我们知道这条其他的边的权值肯定要比u、v之间的权值小 , 因此x、y之间的最短边 = min(u到x之间最短边 ,
v到y之间最短边)。
代码:
int kruskal()
{
sort(edge ,
edge+m , cmp); //对边进行排序
int i , x ,
y , g , h , k = 0;
int sum =
0;
for(i = 0; i
< n; i++)
{
link[i].x =
i+1;
这其实是在求次小生成树 , 因为我们可以知道 ,
次小生成树和最小生成树之间只有一条边不一样 , 因此我们只需要枚举不在最小生成树中边 ,
同时我也要求出该两点在最小生成树中之间的路径中的最长边的值。
解法:我们用kruskal算法来求出最小生成树 , 对于kruskal算法 , 当我们要加入一条边时 , 实际上是在把两颗“树”合并
, 那么从这两颗树上各去除一个点 , 则这两点路径之间的最大边 , 就是当前加入的这条边,因此我们只需要记录每颗树就行了 ,
对于每颗树我们可以用邻接表(数组模拟)来存 。
代码:
int kruskal()
{
sort(edge ,
edge+m , cmp); //对边进行排序
int i , x ,
y , g , h , k = 0;
int sum =
0;
for(i = 0; i
< n; i++) //先把每个点都看成是一颗树
{
link[i].x =
i+1;
link[i].next
= head[i+1];
end[i+1] =
i;
head[i+1] =
i;
}
for(i = 0; ;
i++)
{
if(k ==
n-1) break;
x =
find(edge[i].x); // 判断这两个点是不是在同一颗树上
y =
find(edge[i].y);
if(x !=
y)
{
for(int w =
head[x]; w != -1 ; w = link[w].next)
{
for(int v =
head[y]; v != -1; v = link[v].next)
{
length[link[w].x][link[v].x] = length[link[v].x][link[w].x] =
edge[i].w;
}
}
link[end[x]].next = head[y];//两个树合并成一颗树
end[x] =
end[y];
p[y] = x;
//这是并查集的合并 , 但要和上面的合并相对应
k++;
sum +=
edge[i].w;
}
}
return
sum;
}
2、MST中任意两点路径上的最短边
解法:这和上面的解法差不多 。 也和上面一样 , 用kruskal算法 , 当成是两颗树的合并 。 我假设现在要加入u 、 v这条边
, 并且保证u 、 v不在同一颗树上 , 那么假设点 x 在u 的树上 、 点y在 v的树上 ,
现在我们要求x 、y路径上的最小边 , 如果x就u , y就是v , 那么它们之间的最短边就是u、v之间的权值 , 如果x不是u ,
y不是v , 那么就意味着在x、y的路径上 , 除了u、v这条边之外 , 还有其他的边 ,
并且我们知道这条其他的边的权值肯定要比u、v之间的权值小 , 因此x、y之间的最短边 = min(u到x之间最短边 ,
v到y之间最短边)。
代码:
int kruskal()
{
sort(edge ,
edge+m , cmp); //对边进行排序
int i , x ,
y , g , h , k = 0;
int sum =
0;
for(i = 0; i
< n; i++)
{
link[i].x =
i+1;
相关文章推荐
- poj 3522 MST性质的运用
- uva 11419最小点覆盖和…
- poj 2771 有点难度最大独立集
- poj 2195 最优匹配算法的优化
- zoj 1654 中等二分匹配
- poj 3207 简单的2-SAT问题
- 求强连通分量几种算法的比较
- poj 2762 判断有向图是…
- poj 2553
- poj 3592 有点难度的强…
- 关于求割点代码的一些细节处
- 关于无向图中连通分量缩点的问题
- Reverse Linked List II
- poj 1658 简单的Havel-H…
- poj 3694 中等难度的双…
- poj 3177 有点难度的边-双连通
- zoj 2588 简单的双连通分量
- poj 1144 求图的割点
- poj 1386 欧拉图的应用
- poj 1300 简单的欧拉图…