Boruvka 算法

Boruvka's algorithm

class Edge
{
public:
    int v1;
    int v2;
    int weight;
};
class Subset
{
public:
    int rank;
    int parent;
};
int find(Subset* subsets,int V)
{
    if(subsets[V].parent!=V)
        subsets[V].parent= find(subsets,subsets[V].parent);
    return subsets[V].parent;
}
void union_rank(Subset* subsets,int x,int y)
{
    if(subsets[x].rank>subsets[y].rank)
        subsets[y].parent=x;
    else   if(subsets[x].rank<subsets[y].rank)
                subsets[x].parent=y;
    else
        {
              subsets[y].parent=x;
              subsets[x].rank++;
        }
}
void boruvka(Edge* list,int V,int E)
{
    Subset* subsets=new Subset[V];
int *cheapest = new int[V];
for(int i=0;i<V;i++)
{
    subsets[i].parent=i;
    subsets[i].rank=0;
     cheapest[V] = -1;
}
    int numTrees = V;
    int MSTweight = 0;
    while (numTrees > 1)
    {
          for (int v = 0; v < V; v++)
           {
               cheapest[v] = -1;
           }
        for (int i=0; i<E; i++)
        {
            int x = find(subsets, list[i].v1);
            int y = find(subsets, list[i].v2);
            if (x!=y)
             {
               if (cheapest[x] == -1 || list[cheapest[x]].weight > list[i].weight)
                 cheapest[x] = i;

               if (cheapest[y] == -1 ||list[cheapest[y]].weight > list[i].weight)
                 cheapest[y] = i;
            }
        }
        for (int i=0; i<V; i++)
        {
            if (cheapest[i] != -1)
            {
                int x = find(subsets, list[i].v1);
                int y = find(subsets, list[i].v2);

                if (x==y)
                    continue;
                MSTweight += list[cheapest[i]].weight;
                cout<<list[cheapest[i]].v1<<" "<<list[cheapest[i]].v2<<" "<<list[cheapest[i]].weight<<endl;

                union_rank(subsets, x, y);
                numTrees--;
            }
        }
    }

    printf("Weight of MST is %d\n", MSTweight);
    return;
}
int main()
{
int V, E, tempX, tempY,wt;
cin >>V>>E;
Edge* list=new Edge[E];
for(int i=0;i<E;i++)
{
    cin>>tempX>>tempY>>wt;
    list[i].v1=tempX;
    list[i].v2=tempY;
    list[i].weight=wt;
}
//sort(list,list+E,comp);
boruvka(list,V,E);
    return 0;
}

对于更大的图,我的算法一直进入无限循环有人可以帮我解决这个问题吗?我为非常小的图工作,但任何与此图类似的东西都会进入无限循环loop.I 检查了 numTree 的值,它在某个值后停止减少我不确定为什么。 这是我检查过的图表:

14 20
    0 1 1
    0 2 2
    0 7 3
    1 2 4
    1 3 5
    2 5 6
    3 4 7
    3 10 8
    4 5 9
    4 6 10
    5 9 11
    5 12 12
    6 7 13
    7 8 14
    8 9 15
    8 13 16
    10 11 17
    10 13 18
    11 12 19
    12 13 20

问题出在这个for循环


        for (int i=0; i<V; i++)
        {
            if (cheapest[i] != -1)
            {
                int x = find(subsets, list[i].v1);
                int y = find(subsets, list[i].v2);

                if (x==y)
                    continue;
                MSTweight += list[cheapest[i]].weight;
                cout<<list[cheapest[i]].v1<<" "<<list[cheapest[i]].v2<<" "<<list[cheapest[i]].weight<<endl;

                union_rank(subsets, x, y);
                numTrees--;
            }
        }

您在此处迭代顶点 i=0..V-1 但您正在访问循环内的边列表 list[i] 这是不正确的。

相反,您应该将 for 循环更改为遍历边缘 i=0..E-1 并将循环主体更改为以下内容:

int x = find(subsets, list[i].v1);
int y = find(subsets, list[i].v2);
if (x==y)
  continue;
if (cheapest[x] == list[i].weight || cheapest[y] == list[i].weight) { // this checks if the given edge is the cheapest from the tree containing x or the tree containing y
  MSTweight += list[cheapest[i]].weight;
  union_rank(subsets, x, y);
  union_rank(subsets, x, y);
}