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
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()); } }
2.Constructing Roads (HDU 1102)
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; }