zoukankan      html  css  js  c++  java
  • Kruskal算法:最小生成树

    //Kruskal算法按照边的权值从小到大查看一遍,如果不产生圈(重边等也算在内),就把当前这条表加入到生成树中。

    //如果判断是否产生圈。假设现在要把连接顶点u和顶点v的边e加入生成树中。如果加入之前的u和v不在同一个连通分量里,那么加入e也不会产生圈。

    //反之,如果u和v在同一个连通分量里,那一定会产生圈。可以用并查集高效判断是否属于同一个连通分量。

      1 #define _CRT_SECURE_NO_WARNINGS
      2 /*
      3 7 10
      4 0 1 5
      5 0 2 2
      6 1 2 4
      7 1 3 2
      8 2 3 6
      9 2 4 10
     10 3 5 1
     11 4 5 3
     12 4 6 5
     13 5 6 9
     14 */
     15 #include <iostream>
     16 #include <vector>
     17 #include <algorithm>
     18 using namespace std;
     19 
     20 const int maxn = 1010 + 10;
     21 const int INF = 9999999;
     22 int par[maxn];     //父亲,  当par[x] = x时,x是所在的树的根
     23 int Rank[maxn];    //树的高度
     24 struct edge
     25 {
     26     int u, v, cost;
     27 };
     28 
     29 bool comp(const edge& e1, const edge& e2) {
     30     return e1.cost < e2.cost;
     31 }
     32 
     33 edge es[maxn];
     34 int V, E;        //顶点数和边数
     35 //并查集实现-高效的判断是否属于同一个连通分量。
     36 void init_union_find(int n);
     37 int find(int x);
     38 void unite(int x, int y);
     39 bool same(int x, int y);
     40 void init();
     41 void input();
     42 int kruskal();   //最小生成树算法
     43 
     44 //初始化n个元素
     45 void init_union_find(int n)
     46 {
     47     for (int i = 0; i < n; i++) {
     48         par[i] = i;
     49         Rank[i] = 0;
     50     }
     51 }
     52 
     53 //查询树的根
     54 int find(int x) {
     55     if (par[x] == x) {
     56         return x;
     57     }
     58     else {
     59         return par[x] = find(par[x]);
     60     }
     61 }
     62 
     63 //合并x和y所属集合
     64 void unite(int x, int y) {
     65     x = find(x);
     66     y = find(y);
     67     if (x == y) return;
     68 
     69     if (Rank[x] < Rank[y]) {
     70         par[x] = y;
     71     }
     72     else {
     73         par[y] = x;
     74         if (Rank[x] == Rank[y]) Rank[x]++;    //如果x,y的树高相同,就让x的树高+1
     75     }
     76 }
     77 
     78 //判断x和y是否属于同一个集合
     79 bool same(int x, int y) {
     80     return find(x) == find(y);
     81 }
     82 
     83 void init() {
     84 
     85 }
     86 
     87 void input()
     88 {
     89     edge tmp;
     90     for (int i = 0; i < E; i++) {
     91         cin >> tmp.u >> tmp.v >> tmp.cost;
     92         es[i] = tmp;
     93     }
     94 }
     95 
     96 int kruskal()
     97 {
     98     sort(es, es + E, comp); //按照edge.cost的顺序从小到大排序
     99     init_union_find(V);     //将并查集初始化
    100     int res = 0;
    101     for (int i = 0; i < E; i++) {
    102         edge e = es[i];
    103         if (!same(e.u, e.v)) {
    104             unite(e.u, e.v);
    105             res += e.cost;
    106         }
    107     }
    108     return res;
    109 }
    110 
    111 int main()
    112 {
    113     cin >> V >> E;
    114     input();
    115     int res = kruskal();
    116     cout << res << endl;
    117     return 0;
    118 }
  • 相关阅读:
    内核模式之事件
    用户模式之临界区
    _stdcall与_cdecl区别
    列出系统所有进程
    一道多线程的题
    进程间通信三:父进程传参数与子进程返回值
    进程间通信二:管道技术之命名管道
    进程间通信二:管道技术之匿名管道
    进程间通信二:管道技术之输入输出重定向
    补充实验1:dhcp服务器分配网关-路由器的静态路由优先级
  • 原文地址:https://www.cnblogs.com/douzujun/p/6418281.html
Copyright © 2011-2022 走看看