数据结构和算法分析数据结构和算法分享专题

最小生成树算法

2018-06-06  本文已影响8人  周九九丶

最小生成树

给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一棵树,那么这棵树就叫做生成树。如果边上有权值,那么使得权值最小的生成树叫做最小生成树


Prim算法

Prim算法和Dijktra算法十分相似,都是从某个顶点出发,不断添加边的算法。不同的是Dijkstra算法每次添加的点在所有未添加的点中到原点的距离最小,Prim算法每次添加的点在所有未添加的点中到T中的点的距离最小

算法思路

首先,我们假设有一棵只包含一个顶点v的树T。然后贪心的选取T和其他顶点之间相连的最小权值的边,并把边的另一节点加到T中。不断进行这个操作就可以得到最小生成树。

算法过程
代码

用邻接矩阵表示图

用优先级队列选出距离最小的节点

#include <iostream>
#include <queue>
using namespace std;

typedef pair<int, int> p;

struct mycmp{
    bool operator()(p p1, p p2){
        return p1.second > p2.second;
    }
};

const int INF = 10000;
const int MAX_V = 100;

int g[MAX_V][MAX_V];//graph
int included[MAX_V];//included[i]=1 when node i is included in MST
int d[MAX_V];//current distance to T
int vNum;
int eNum;
int res;

void init(){
    res = 0;
    for(int i = 0; i < vNum; i++){
        included[i] = 0;
        d[i] = INF;
        for(int j = 0; j < vNum; j++){
            g[i][j] = INF;
        }
    }
}

void addEdge(int u, int v, int w){
    g[u][v] = w;
    g[v][u] = w;
}

void Prim(){
    priority_queue<p, vector<p>, mycmp> q;
    d[0] = 0;
    q.push(make_pair(0, d[0]));
    while(!q.empty()){
        int u = q.top().first;
        int du = q.top().second;
        q.pop();
        if(included[u]) continue;
        res += du;
        included[u] = 1;
        printf("include:%d\n", u);
        for(int i = 0; i < vNum; i++){
            if(!included[i] && d[i] > g[u][i]){
                d[i] = g[u][i];
                q.push(make_pair(i, d[i]));
            }
        }
    }
}

int main(){
    scanf("%d %d", &vNum, &eNum);
    init();
    for(int i = 0; i < eNum; i++){
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        addEdge(u, v, w);
    }
    Prim();
    printf("%d\n", res);
    return 0;
}

Kruskal算法

算法思路

Kruskal算法按照边的权值从小到大的顺序访问边,如果访问的边与当前生成树不产生回路,就把这条边添加到生成树中。

算法实现

代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int MAX_E = 10000;
const int MAX_V = 100;

struct Edge{
    int u, v, w;
    Edge(int u, int v, int w){
        this->u = u;
        this->v = v;
        this->w = w;
    }
    bool operator < (const Edge &e){
        return w < e.w;
    }
};

/*bool mycmp(const Edge &e1, const Edge &e2){
    return e1.w < e2.w;
}*/

vector<Edge> edges;
int vNum;
int eNum;
int res;
int p[MAX_V];
int r[MAX_V];

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

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

void Union(int x, int y){
    int xRoot = Find(x);
    int yRoot = Find(y);
    if(r[x] < r[y]) p[xRoot] = yRoot;
    else{
        p[yRoot] = xRoot;
        if(r[xRoot] == r[yRoot]) r[xRoot]++;
    }
}

bool sameRoot(int x, int y){
    return Find(x) == Find(y);
}

void Kruskal(){
    vector<Edge>::iterator it;
    for(it = edges.begin(); it != edges.end(); ++it){
        int u = (*it).u;
        int v = (*it).v;
        int w = (*it).w;
        printf("%d %d %d\n", u, v, w);
        if(!sameRoot(u, v)){
            Union(u, v);
            res += w;
        }   
    }
}

int main(){
    scanf("%d %d", &vNum, &eNum);
    init();
    for(int i = 0; i < eNum; i++){
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        edges.push_back(Edge(u, v, w));
    }   
    //sort(edges.begin(), edges.end(), mycmp);
    sort(edges.begin(), edges.end());
    Kruskal();
    printf("%d\n", res);
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读