Both methods substantially minimum spanning tree template

Minimum spanning tree (Kruskal (Kruskal) and Prim (Prim)) algorithm Animation

Prim algorithm is suitable for dense graph
Kruskal suitable for sparse graphs

prim algorithm

Start from the apex, connected to two preferred set of vertices (vertex set selected and unselected vertex set) all the edges, the minimum weight value, while moving the selected vertex to vertex set
to repeat the same procedure

Implementation: three updated list
1 stores whether the vertex is selected to true: the set of vertices selected false: unselected vertex set
2 at a time, all connected to the selected vertex in the set of edge weights to the vertex that the minimum value of the size of the right sides, the initial state are INF
3. stored minimum weight side ends vertex information.
Determining two vertices of an edge, it is initially -1 indicates the absence of

Selecting a start vertex, when added to each of the selected set a new vertex, a list of all the update information attached to the vertex and vertices

Since the beginning of the weights is set to INF
if a point and this point right system exists, and less than INF, update the parent list, updated weights,

Next, scan lists the minimum weight value, corresponding to the vertex to find the minimum value
will be changed to select whether true,

Followed by the vertex operation is repeated for the new vertex

update——scan——add

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>

#define ll long long
using namespace std;
//const int mod=;
#define INF 0x3f3f3f3f
const int maxn=10010;

int n,m; //n个点
int mat[maxn][maxn]; //
bool vis[maxn]; //看是否选择过
int d[maxn];    //记录任意一点到这个点的最近距离

int main(void){
    cin >> n;
    //邻接矩阵
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            cin >> mat[i][j];
    
    memset(d,INF,sizeof(d));
    memset(vis,0,sizeof(vis));
    
    int ans = 0;
    d[1] = 0; //从1开始,那么1到已选集合距离为0
    
    for(int i=1; i<=n; i++){
        int end = -1;
        
        for(int j=1; j<=n; j++){        //每次都遍历未选集合内的所有点
            if(!vis[j] && (end == -1||d[j]<d[end])) //总有一个比INF小
                end = j; //d[j]是最优的
        }
        ans += d[end];
        vis[end] = 1;     //用过了,标记到已选集合
        
        for(int j=1; j<=n; j++){
            //加了一个新的点进去,新的已选区域,这个新的点相连的边也加到可选列表内
            if(!vis[j] && mat[end][j]<d[j])
                //end是新加的,比较到j权值,j点之前可能已经添加过,所以比较,选择最小的
                d[j] = mat[end][j];
        }
    }
    cout << ans << endl;
    return 0;
}

Kruskal's algorithm

The weights in ascending order, each selected from the smallest, is determined whether the current FIG ring, a ring: discard, selected from a next
sequence, until the number of selected n-1 side is

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
//const int mod=;
#define INF 0x3f3f3f3f
const int maxn=1e6+10;

int n,m; //n个点m个边
//存边的数据
struct node{
    int from,to,val;
}edge[maxn];

bool cmp(node x,node y){
    return x.val < y.val;
}
int pre[maxn];

//并查集
int find(int x){
    return x == pre[x]?x:pre[x] = find(pre[x]);
}
void Union(int x,int y){
    pre[find(x)] = find(y);
}
int main(void){
    cin >> n >> m;
    int ans = 0;
    
    for(int i=0; i<=n; i++)
        pre[i] = i;
    
    for(int i=1; i<=m; i++)
        cin >> edge[i].from >> edge[i].to >> edge[i].val;
    
    sort(edge+1,edge+m+1,cmp);
    
    //扫描所有边
    for(int i=1; i<=m; i++){
        //如果一个是在有效集合,一个在无效集合:不能构成环,就连接起来——并查集
        if(find(edge[i].from) != find(edge[i].to)){
            ans += edge[i].val;
            Union(edge[i].from,edge[i].to);
        }
    }
    
    cout << ans << endl;
    
    return 0;
}

Published 36 original articles · won praise 0 · Views 975

Guess you like

Origin blog.csdn.net/jhckii/article/details/104302839