MST 的 Kruskal 算法的 C 实现
我正在研究 Kruskal 的算法,用于查找给定图的 MST,并且我理解基本概念,即您必须首先将所有顶点视为森林。之后,您必须找到最小边并将边的顶点连接成一棵树。并递归地执行此操作,直到只剩下一棵包含所有顶点的树。
我遇到了该算法的以下实现。
#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;
I was studying Kruskal's algorithm for finding the MST for a given graph and i understand the basic concept that you have to consider all the vertices as a forest initially. After that you have to find the minimum edge and joining the vertices of the edge into one tree. And doing this recursively until only one tree containing all the vertices is left.
And i came across the following implementation of this algorithm.
#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);
}
What i don't understand is the need for:
while(p[u])
u=p[u];
while(p[v])
v=p[v];
What exactly do those two while loops do?
edit: and also the necessity of-
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(w[i][j]==0)
w[i][j]=999;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Kruskals算法想要添加某个边
(a, b)
。但是,在这样做之前,它必须检查a
和b
是否已连接(如果是,则不会添加边缘)。您给定的四行只是检查
a
和b
是否已连接。要完全理解这一点,您必须了解以下内容:最初
u
和v
设置为a
和b
, 分别。数组p
存储连通分量。即p[x] = y
表示:x
位于y
的连通分量中。请注意,最初每个顶点代表其自己的连接组件,由p[n1] = 0, p[n2] = 0, ...
表示(即组件设置为 0)。此外,请注意,每个连接的组件都由一个顶点表示。
所以,我们开始:
while(p[u])
检查u
是否代表一个组件(u
是一个代表 iffp[u] == 0
,这会导致 while 循环停止)。因此,如果u
是组件的代表,则它将停止。更有趣的部分如下:如果
u
不是代表,算法会查找p[u]
,即查找哪个节点是该组件的代表u
。然后它相应地更新u
(u=p[u]
)。您可以将整个游戏视为一个图表。考虑下表表示连接的组件:
这意味着节点
1
属于由2
表示的组件。4
属于3
表示的组件,而3
本身又属于2
表示的组件。请注意,2
是一个代表,因为它具有条目0
。您可以将其可视化为图表:
您看,我们当前有 3 个组件,分别用 2、7 和 9 表示。
如果我们现在想要添加一条新边
(6,7)
,我们必须“沿着树向上”,直到分别找到代表 2 和 7。正如我们所看到的,代表并不相同,我们添加了边缘。现在另一个例子:我们想要添加边
(6, 5)
,因此我们“沿着树向上”并在两种情况下找到代表2
。因此,我们不添加边缘。“上树”是由你明确说出的台词完成的。
Kruskals algorithm wants to add a certain edge
(a, b)
. However, before doing so, it has to check whethera
andb
are already connected (if they are, it won't add the edge).Your four given lines do just that check whether
a
andb
are already connected.To understand this completely, you have to know the following: Initially
u
andv
are set toa
andb
, respectively. The arrayp
stores the connected components. That isp[x] = y
means:x
lies in the connected component ofy
. Note that initially each vertex represents its own connected component, indicated byp[n1] = 0, p[n2] = 0, ...
(i.e. the component is set to 0).Moreover, note that each connected component is represented by one vertex.
So, here we go:
while(p[u])
checks whetheru
is representant of a component (u
is a representant iffp[u] == 0
, which causes the while loop to stop). So, ifu
is the representant of a component, it stops.The more interesting part is the following: If
u
is not a representant, the algorithm looks upp[u]
, i.e. it looks up which node is the representant of the component ofu
. Then it updatesu
accordingly (u=p[u]
).You can consider this whole game as a graph. Consider the following table representing connected components:
This means, that node
1
belongs to component represented by2
.4
belongs to component represented by3
, which itself belongs to component represented by2
. Note that2
is a representant because it has entry0
.You can visualize this as a graph:
You see, we have currently 3 components represented by 2, 7 and 9, respectively.
If we now want to add a new edge
(6,7)
, we have to "go up the trees" until we find the representants 2 and 7, respectively. As we see, the representants are not the same, we add the edge.Now another example: We want to add edge
(6, 5)
, so we "go up the tree" and find representant2
in both cases. Thus, we don't add the edge."Going up in the trees" is done by the lines that were explicitly stated by you.