问题:用Floyd算法将给定的图(9个节点的连通图)分成三个簇
1.什么是分簇?
分簇:将一个图分成很多个子图,但是有要求。
分簇要求:每个子图的含有的节点之间一定是最大密度的。也就是说,每个子图是最小生成树的一部分。
2.实现方法
使用Floyd最小生成树算法来实现:
step 1:将所给的边按权值由小到大的排序。
step 2:设置一个下标为节点的数组visited来表示并查集。数组初始化时,按每个位置的下标赋值,保证每个节点都不在同一集合内。
step 3:对所有排好序的边,如果这边的两端节点所在的visited数组中的值不一样,那么该边是最小生成树中的一条边,将边的信息输出,而后,遍历visited数组,将所有与第二个节点在同一集合(也就是visited数值等于第二个节点在visited中的数值的位置)都赋值为第一个节点在visited中的值。
如果两端点所在visited数组中的值一样,则跳过这条边。
step 4:也是最重要的一条,由于是把图分成三个簇,那么最小生成树的最后两条有效边是不用找了的。因为是九个节点,所以最小生成树中有8条边,而按照Floyd算法,最小生成树中最大的两条边肯定是最后才会出来的,所以,就可以保证每个子图中的点之间是最大密度化的。因此我们要舍弃将要找到的最后两条边。
3.伪代码(感觉伪代码比代码更好理解)
main:
for all i in visited[]:
visited[i] = i;
for all edges in the graph:
cin>>edge;
sort all edges;(small->big)
for all edges:
{
if(visited[edge.first_node] != visited[edge.second_node])
{
cout<<edge;
int temp = visited[edge.second_node];
for all nodes in visited[]:
{
if(visited[node] == temp)
{
visited[node] = visited[edge.first_node];
}
}
cont++;
}
if(cont == 6)
break;
}
附图的数据:
1 2 2
1 3 3
2 3 5
2 4 10
2 5 2
3 5 1
3 7 2
4 6 1
4 8 4
5 6 3
5 7 -2
6 7 5
6 8 2
6 9 3
7 9 2
8 9 1