4

我正在研究为给定图查找 MST 的 Kruskal 算法,并且我了解最初必须将所有顶点视为森林的基本概念。之后,您必须找到最小边并将边的顶点连接成一棵树。并递归地执行此操作,直到只剩下一棵包含所有顶点的树。

我遇到了这个算法的以下实现。

#include<iostream.h>

int p[10];

void kruskal(int w[10][10],int n)
{
    int min,sum=0,ne=0,i,j,u,v,a,b;
    for(i=1;i<=n;i++)
    p[i]=0;
    while(ne<n-1)
    {
        min=999;
        for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            if(w[i][j]<min)
            {
                    min=w[i][j];
                u=a=i;
                v=b=j;
            }
        }
        while(p[u])
            u=p[u];
        while(p[v])
            v=p[v];
        if(u!=v)
        {
            ne++;
            sum+=min;
            cout<<"\nedge "<<a<<"-->"<<b<<" is "<<min;
            p[v]=u;
        }
        w[a][b]=w[b][a]=999;
    }
    cout<<"\nmin cost spanning tree= "<<sum;
}

void main()
{
    int w[10][10],n,i,j;
    clrscr();
    cout<<"enter no.of vertices\n";
    cin>>n;
    cout<<"enter weight matrix\n";
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            cin>>w[i][j];
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(w[i][j]==0)
                w[i][j]=999;
    kruskal(w,n);
}

我不明白的是需要:

while(p[u])
    u=p[u];
while(p[v])
    v=p[v];

这两个 while 循环究竟做了什么?

编辑:还有——

for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(w[i][j]==0)
                w[i][j]=999; 
4

1 回答 1

9

Kruskals 算法想要添加一定的边缘(a, b)。但是,在这样做之前,它必须检查是否ab已经连接(如果是,则不会添加边缘)。

a您给定的四行只是检查是否b已连接。

要完全理解这一点,您必须了解以下内容: 最初uv分别设置为ab。该数组p存储连接的组件。也就是说p[x] = yx位于 的连通分量中y。请注意,最初每个顶点表示其自己的连接组件,由p[n1] = 0, p[n2] = 0, ...(即组件设置为 0)表示。

此外,请注意,每个连接的组件都由一个顶点表示。

所以,我们开始:while(p[u])检查是否u是组件的代表(u是代表 iff p[u] == 0,这会导致 while 循环停止)。所以,如果u是一个组件的代表,它就会停止。

更有趣的部分如下: 如果u不是代表,则算法查找p[u],即查找哪个节点是 的组件的代表u。然后它会u相应地更新 ( u=p[u])。

您可以将整个游戏视为一个图表。考虑下表表示连接的组件:

   u  |  1  2  3  4  5  6  7  8  9
 p[u] |  2  0  2  3  2  1  0  9  0

这意味着,该节点1属于由 表示的组件24属于由 表示的组件3,它本身属于由 表示的组件2。请注意,这2是一个代表,因为它有 entry 0

您可以将其可视化为图表:

  2      7  9
 /|\        |
1 3 5       8
| |
6 4

你看,我们目前有 3 个组件,分别用 2、7 和 9 表示。

如果我们现在想添加一条新边(6,7),我们必须“上树”,直到分别找到代表 2 和 7。正如我们所看到的,代表不一样,我们添加边缘。

现在再举一个例子:我们想添加 edge (6, 5),所以我们“上树”并2在这两种情况下找到代表。因此,我们不添加边缘。

“在树上爬上去”是由您明确说明的行完成的。

于 2011-11-20T12:06:25.743 回答