当前位置: 首页 > article >正文

C++ 算法学习——1.9 Kruskal算法

Kruskal算法是一种用于解决最小生成树(Minimum Spanning Tree)问题的贪婪算法。 

Kruskal算法步骤:

  1. 初始化:将图中的所有边按照权值从小到大进行排序。

  2. 创建并查集:为每个顶点创建一个集合,用于判断两个顶点是否在同一个连通分量中。

  3. 遍历排序后的边:从权值最小的边开始遍历。

  4. 检查边的两个顶点

    • 如果这两个顶点不在同一个连通分量中,则将它们加入最小生成树中,并合并它们的连通分量。
    • 如果这两个顶点已经在同一个连通分量中,则跳过这条边,以避免形成环路。
  5. 重复步骤4,直到最小生成树中有V-1条边(V为顶点数),此时最小生成树构建完成。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Edge {
    int src, dest, weight;
    Edge(int a,int b,int c):src(a),dest(b),weight(c){}
};

struct Graph {
    int V, E;
    vector<Edge> edges;
    Graph(int a,int b):V(a),E(b){}
};

int find(vector<int>& parent, int i) {
    while (parent[i] != i) {
        i = parent[i];
    }
    return i;
}

void Union(vector<int>& parent, int x, int y) {
    int xset = find(parent, x);
    int yset = find(parent, y);
    parent[xset] = yset;
}

void KruskalMST(Graph& graph) {
    int V = graph.V;
    vector<Edge> result;
    int e = 0, i = 0;

    sort(graph.edges.begin(), graph.edges.end(), [](const Edge& a, const Edge& b) {
        return a.weight < b.weight;
    });

    vector<int> parent(V);
    for (int v = 0; v < V; v++) {
        parent[v] = v;
    }

    while (e < V - 1 && i < graph.E) {
        Edge next_edge = graph.edges[i++];

        int x = find(parent, next_edge.src);
        int y = find(parent, next_edge.dest);

        if (x != y) {
            result.push_back(next_edge);
            Union(parent, x, y);
            e++;
        }
    }

    //cout << "Edges in the constructed MST:\n";
    for (const Edge& edge : result) {
        cout << edge.src << " -- " << edge.dest << " == " << edge.weight << endl;
    }
}

int main()
{
    int n,m;cin>>n>>m;
    Graph mygraph(n,m);
    for(int i=1;i<=m;i++)
    {
        int a,b,c;cin>>a>>b>>c;
        Edge p(a,b,c);
        mygraph.edges.push_back(p);
    }
    return 0;
}

 说明:

  • e < V - 1:这个条件是用来判断当前已经加入最小生成树的边数是否达到了顶点数减一,即 V - 1。在一个连通的图中,最小生成树的边数必定是顶点数减一。

  • i < graph.E:这个条件是用来确保遍历完所有的边。graph.E 表示图中边的总数,i 是当前处理到的边的索引。这个条件保证在所有边都遍历完之前继续尝试找到最小生成树的边。


P1. 洛谷p3366最小生成树 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
int ans=0;
struct Edge {
    int src, dest, weight;
    Edge(int a,int b,int c):src(a),dest(b),weight(c){}
};

struct Graph {
    int V, E;
    vector<Edge> edges;
    Graph(int a,int b):V(a),E(b){}
};

int find(vector<int>& parent, int i) {
    while (parent[i] != i) {
        i = parent[i];
    }
    return i;
}

void Union(vector<int>& parent, int x, int y) {
    int xset = find(parent, x);
    int yset = find(parent, y);
    parent[xset] = yset;
}

void KruskalMST(Graph& graph) {
    int V = graph.V;
    vector<Edge> result;
    int e = 0, i = 0;

    sort(graph.edges.begin(), graph.edges.end(), [](const Edge& a, const Edge& b) {
        return a.weight < b.weight;
    });

    vector<int> parent(V);
    for (int v = 0; v < V; v++) {
        parent[v] = v;
    }

    while (e < V - 1 && i < graph.E) {
        Edge next_edge = graph.edges[i++];

        int x = find(parent, next_edge.src);
        int y = find(parent, next_edge.dest);

        if (x != y) {
            result.push_back(next_edge);
            Union(parent, x, y);
            e++;
            ans+=next_edge.weight;
        }
    }
    if(e!=V-1) cout<<"orz";
    else cout<<ans; 

    //cout << "Edges in the constructed MST:\n";
    //for (const Edge& edge : result) {
        //cout << edge.src << " -- " << edge.dest << " == " << edge.weight << endl;
    //}
}

int main()
{
    int n,m;cin>>n>>m;
    Graph mygraph(n,m);
    for(int i=1;i<=m;i++)
    {
        int a,b,c;cin>>a>>b>>c;
        Edge p(a-1,b-1,c);
        mygraph.edges.push_back(p);
    }
    KruskalMST(mygraph);
    return 0;
}

P2. 洛谷p1194买礼物

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
int ans=0;
struct Edge {
    int src, dest, weight;
    Edge(int a,int b,int c):src(a),dest(b),weight(c){}
};

struct Graph {
    int V, E;
    vector<Edge> edges;
    Graph(int a,int b=0):V(a),E(b){}
};

int find(vector<int>& parent, int i) {
    while (parent[i] != i) {
        i = parent[i];
    }
    return i;
}

void Union(vector<int>& parent, int x, int y) {
    int xset = find(parent, x);
    int yset = find(parent, y);
    parent[xset] = yset;
}

int KruskalMST(Graph& graph) {
    int V = graph.V;
    graph.E = graph.edges.size();
    vector<Edge> result;
    int e = 0, i = 0;

    sort(graph.edges.begin(), graph.edges.end(), [](const Edge& a, const Edge& b) {
        return a.weight < b.weight;
    });

    vector<int> parent(V);
    for (int v = 0; v < V; v++) {
        parent[v] = v;
    }

    while (e < V - 1 && i < graph.E) {
        Edge next_edge = graph.edges[i++];

        int x = find(parent, next_edge.src);
        int y = find(parent, next_edge.dest);

        if (x != y) {
            result.push_back(next_edge);
            Union(parent, x, y);
            e++;
            ans+=next_edge.weight;
        }
    }
    return ans;

    //cout << "Edges in the constructed MST:\n";
    //for (const Edge& edge : result) {
        //cout << edge.src << " -- " << edge.dest << " == " << edge.weight << endl;
    //}
}

int main()
{
    int n,m;cin>>n>>m;
    Graph mygraph(m);
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++)
        {
            int weight;cin>>weight;
            if(weight)
            {
                Edge p(i,j,min(n,weight));
                mygraph.edges.push_back(p);
            }
            if(!weight)
            {
                Edge p(i,j,n);
                mygraph.edges.push_back(p);
            }
        }
    }
    cout<<n+KruskalMST(mygraph);
    return 0;
}

 


http://www.kler.cn/news/358252.html

相关文章:

  • 平安养老险深圳分公司:创新养老服务,深入践行金融为民
  • SQLite数据库在Android中的应用及操作方式
  • Python | Leetcode Python题解之第486题预测赢家
  • leetcode day1
  • Python Django 查询集的延迟加载特性
  • BERT论文关键点解读与常见疑问
  • 无人机之自主飞行关键技术篇
  • 苍穹外卖学习笔记(二十五)
  • Vue前置基础
  • 2024软件测试面试800题(答案+文档)
  • list(1)
  • 设计模式一--单例设计模式
  • WebStorm小白下载安装教程
  • Flink窗口分配器WindowAssigner
  • centOS实用命令
  • 一图秒懂色彩空间和色彩模型
  • HarmonyOS开发(状态管理,页面路由,动画)
  • MySQL面试专题-索引
  • 缓存常见问题:缓存穿透、雪崩、击穿及解决方案分析
  • Java中的校验性判断