Minimum Spanning Tree - Prim's Algorithm and Kruskal's Algorithm

 

  Before solving this problem, I feel it is necessary to explain what is called a spanning tree and what is called a minimum spanning tree. Given a graph, if any two vertices in one of its subgraphs are connected to each other and are a tree, then the tree is called a spanning tree. If the edges have weights, the tree that minimizes the sum of the weights is called a minimum spanning tree.

  Safe edge: When an edge (u, v) joins T, it must be guaranteed that T∪{(u, v)} is still a subset of MST, and we call such an edge a safe edge of T.

  The general algorithm for finding MST (minimum spanning tree) can be described as: for the graph G, starting from the empty tree T, select and add n-1 safe edges (u, v) to the set T one by one, and finally generate a tree containing n - MST for 1 side . There are two main ways to solve the minimum spanning tree:

  1. Prim algorithm:

  Greedily add the edge with the smallest weight connecting the MST to other vertices to the MST, and repeat the operation until there are n edges in the MST. If we want to use Prim's algorithm efficiently, we can use min heap. Here's a diagram of the algorithm:

----------------------------------------------------------------------------------------------------------------------------------------

Second, the kruskal algorithm

Kuskal's greedy strategy is easier to understand: the safe edge with the smallest weight is selected each time, and then added to the MST until there are n-1 edges in the MST. Of course, efficient search requires the use of union search sets, such as the second example below, and the use of minimum heaps. See kruskal's diagram below:

 

 ----------------------------------------------------------------------------------------------------------------------------------------

Three, classic topics:

1.HDU 1233

or smooth engineering

describe

A province investigates rural traffic conditions, and the obtained statistical table lists the distance between any two villages. The goal of the provincial government's "unblocked project" is to enable road traffic between any two villages in the province (but not necessarily directly connected by road, as long as it can be reached indirectly by road), and requires the total length of the road to be paved to the minimum. Please calculate the minimum total road length. 

Input

Test input contains several test cases. The first line of each test case gives the number of villages N ( < 100 ); the subsequent N(N-1)/2 lines correspond to the distance between villages, and each line gives a pair of positive integers, which are the two villages number, and the distance between the two villages. For simplicity, villages are numbered from 1 to N. 
When N is 0, the input ends and the use case is not processed.

 
Output

For each test case, output the minimum total road length on 1 line. 


Sample Input

3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0

Sample Output

3
5

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=105;
const int INF=0x3fffffff;
int graph[maxn][maxn];
int n;
int Prim()
{
    int min_cost[maxn];
    bool used[maxn];
    for(int i=0;i<maxn;i++)
    {
        min_cost[i]=INF;
        used[i]=false;
    }
    min_cost [ 1 ] = 0 ;
    int res = 0 ;

    while(1)
    {
        int v=-1;
        for(int u=1;u<=n;u++)
        {
            if(!used[u]&&(v==-1||min_cost[u]<min_cost[v])) v=u;
        }

        if(v==-1)
            break;

        used[v]=true;
        res+=min_cost[v];

        for(int u=1;u<=n;u++)
        {
            min_cost[u]=min(min_cost[u],graph[v][u]);
        }
    }
    return res;
}

intmain ()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<=n;i++)
            for(int j=0;j<maxn;j++)
                graph[i][j]=INF;
        int vertex1,vertex2,weight;
        for(int i=1;i<=n*(n-1)/2;i++)
        {
            scanf("%d%d%d",&vertex1,&vertex2,&weight);
            graph[vertex1][vertex2]=weight;
            graph[vertex2][vertex1]=weight;
        }
        printf("%d\n",Prim());
    }
}
View Code

 

2.Constructing Roads  (HDU 1102)

There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected. 

We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum. 

InputThe first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j. 

Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built. 
OutputYou should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum. 
Sample Input

3
0 990 692
990 0 179
692 179 0
1
1 2

Sample Output

179

#include<set>
#include<cstdio>
using namespace std;

struct Node
{
    int x,y,cost;
    Node() {}
    Node(int xx,int yy,int cc):x(xx),y(yy),cost(cc){}
    friend bool operator<(Node a,Node b);
};

const  int maxn = 10000 ;
int fa [maxn];

void init()
{
    for(int i=0;i<maxn;i++) fa[i]=i;
}

int GetRoot ( int x)
{
    if(x!=fa[x])
    {
        return fa[x]=GetRoot(fa[x]);
    }

    return fa[x];
}

void Unite(int x,int y)
{
    int fx = GetRoot (x);
    int fy = GetRoot (y);
    fa [fx] = fy;
}

intmain ()
{
    int n;
    multiset<Node> s;
    while(~scanf("%d",&n))
    {
        init();
        s.clear();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                int num;
                scanf("%d",&num);
                if(i!=j)
                {
                    s.insert(Node(i,j,num));
                }
            }
        }
        int q,ans= 0 ,counter= 0 ;   // counter represents the number of connected edges 
         scanf( " %d " ,& q);
         while (q-- )
        {
            int xx,yy;
            scanf("%d%d",&xx,&yy);
            if(GetRoot(xx)!=GetRoot(yy))
                counter++;
            Unite(xx,yy);
        }
        multiset<Node>::iterator it=s.begin();
        while(counter<n-1)
        {
            Node node = (* it);
            int rx = GetRoot (node.x);
            int ry = GetRoot (node.y);
            if (rx! = ry)
            {
                Unite (rx, ry);
                ans+=it->cost;
                counter++;
            }
            it++;
        }
        printf("%d\n",ans);
    }
}

bool operator<(Node a,Node b)
{
    return a.cost<b.cost;
}
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325215600&siteId=291194637
Recommended