[Graph Theory - Lecture 8] Kruskal Algorithm for Minimum Spanning Tree Problem

ฅ(๑˙o˙๑)ฅ Hello everyone, welcome to my blog: The series of learning notes for Ania learning algorithms is continuously updated~

A



I. Introduction

Minimum spanning tree definition:

A spanning tree of a connected graph with n nodes is a minimal connected subgraph of the original graph, and contains all n nodes in the original graph, and has the fewest edges that keep the graph connected. The minimum spanning tree can be calculated by kruskal algorithm or prim algorithm.

Minimum spanning tree is actually 最小权重生成树short for


Second, Kruskal algorithm to find the minimum spanning tree

Time complexity O(mlogm) - m is the number of edges, suitable for finding the minimum spanning tree of the network with sparse edges

Kruskal's algorithm is based on the idea of ​​greedy.

Brief description of Kruskal algorithm

First, we arrange all the edges according to the weights from small to large, and then select each edge in order. If the two endpoints of this edge do not belong to the same set, then merge them until all the points belong to the same set. until the collection.

Implementation steps

  • Sort all the edges in ascending order according to the size of the weights, and then judge them one by one from small to large.

  • If this edge does not form a circuit with all the previously selected edges, select this edge to divide; otherwise, discard it.

  • Until a connected network with n vertices filters out n-1 edges.

  • The selected edges and all vertices constitute the minimum spanning tree of this connected network.

The method of judging whether there will be a loop is: use union search .

Each vertex is given a different set in the initial state.
Traverse each edge of the process to determine whether the two vertices are in a set.
If the two vertices on the edge are in a set, it means that the two vertices are connected, and this edge is not required. If not in a set, this edge is required.

int Kruskal()
{
    
    
    int res=0,cnt=0;//res记录最小生成树的树边权重之和,cnt记录的是全部加入到树的集合中边的数量(可能有多个集合)
    for(int i=0;i<m;i++)
    {
    
    
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        if(find(a)!=find(b))
        //如果 a b 不在一个集合中
        {
    
    
            p[find(a)]=p[find(b)];//将a,b所在的两个集合连接起来
            cnt++;//因为加入的是a-b的这一条边,将a,b所在的两个集合连接之后,全部集合中的边数加1
            res+=w;//加入到集合中的边的权重之和
        }
    }

    if(cnt==n-1) return res;//树中有n个节点便有n-1条边,可以生成最小生成树
    else return 0x3f3f3f3f;//如果cnt不等于n-1的话,说明无法生成有n个节点的树
}

example:

Given an undirected graph with n points and m edges, there may be multiple edges and self-loops in the graph, and the edge weights may be negative.
Find the sum of the tree edge weights of the minimum spanning tree, and output impossible if the minimum spanning tree does not exist.

Input samples:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
Output samples:
6

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N=200010,M=100010;         

int p[M];
int n,m;

struct Edge
{
    
    
    int a,b,w;
//重载小于号,因为在给边排序的时候是按照边的权重进行排序的,这样当两个边进行比较的时候就会使用它们的权重进行比较了
     bool operator< (const Edge &W)const
    {
    
    
        return w < W.w;
    }
}edges[N];

int find(int x)
{
    
    
    if(p[x]!=x) p[x]=find(p[x]);
    else return x;
} 

int Kruskal()
{
    
    
    int res=0,cnt=0;//res记录最小生成树的树边权重之和,cnt记录的是全部加入到树的集合中边的数量(可能有多个集合)
    for(int i=0;i<m;i++)
    {
    
    
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        if(find(a)!=find(b))
        {
    
    
            p[find(a)]=p[find(b)];//将a,b所在的两个集合连接起来
            cnt++;//因为加入的是a-b的这一条边,将a,b所在的两个集合连接之后,全部集合中的边数加1
            res+=w;//加入到集合中的边的权重之和
        }
    }

    if(cnt==n-1) return res;//可以生成最小生成树
    else return 0x3f3f3f3f;//树中有n个节点便有n-1条边,如果cnt不等于n-1的话,说明无法生成有n个节点的树
}

int main()
{
    
    
    cin>>n>>m;

    for(int i=0;i<n;i++) p[i]=i;//初始化并查集

    for(int i=0;i<m;i++)//读入每条边
    {
    
    
        int a,b,w;
        cin>>a>>b>>w;
        edges[i]={
    
    a,b,w};
    }

    sort(edges,edges+m);//将边的权重按照大小一一排序

    int t=Kruskal();

    if(t==0x3f3f3f3f) puts("impossible\n");
    else cout<<t<<endl;

    return 0;
}

at last

Mo Yan, the truth is endless, every inch of progress has its own

insert image description here

Guess you like

Origin blog.csdn.net/m0_63233163/article/details/125608760