zoukankan      html  css  js  c++  java
  • 数据结构4 并查集

    • 查找的时候才更新的时候
    • 合并的时候不更新
     1 #include  <iostream>
     2 using namespace std;
     3 #define N 100
     4 int father[N];
     5 int n, m;
     6 
     7 void init(){
     8     for(int i=1; i<=n; i++)
     9         father[i] = i;
    10 }
    11 
    12 //查找
    13 int Find(int x){
    14     if(x != father[x])
    15         father[x] = Find(father[x]);
    16     return father[x]; // 一直要找到 x = father[x] 返回
    17 }
    18 
    19 
    20 // 合并
    21 void Union(int x, int y){
    22     int a, b;
    23     a = Find(x);
    24     b = Find(y);
    25     if(a != b)
    26         father[b] = a;  // 这边是随便给的,没有影响
    27 }
    28 
    29 int main(){
    30     int x, u, v, sum=0;
    31     cout << "input n and m:" << endl;
    32     cin >> n >> m;
    33     init();
    34     cout << "input u and v" << endl;
    35     for(int i=1; i<=m; i++){
    36         cin >> u >> v;
    37         Union(u, v);
    38     }
    39     
    40     for(int i=1; i<=n; i++){
    41         Find(i);  // 每次查找的时候更新数组
    42         cout << father[i] << " ";
    43         if(father[i]==i)
    44             sum++;
    45     }
    46     cout << endl;
    47     cout << "sum=" << sum << endl;
    48     return 0;
    49 }

    测试数据:

     10 9

     1 2

     3 4

     5 2

     4 6

     2 6

     8 7

     9 7

     1 6

     2 4

    每个节点都执行一次find,来完成路径压缩。

    使用并查集改进Kruskal

    先对边排序,然后使用并查集选边

     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 const int N=100;
     6 int father[N];
     7 int n, m;  // 节点数,边数
     8 
     9 struct Edge{  // kruskal对边进行排序
    10     int u, v, w;
    11 }e[N*N];
    12 // 有向图 n(n-1)/2  无向图 n(n-1)
    13 
    14 bool cmp(Edge x, Edge y){
    15     return x.w < y.w;
    16 }
    17 
    18 void Init(int n){  // 节点从1到n
    19     for(int i=1; i<=n; i++)
    20         father[i] = i;
    21 }
    22 
    23 int Find(int x){
    24     if(x != father[x])
    25         father[x] = Find(father[x]);  // 调用它父亲的集合号
    26     return father[x];
    27 }
    28 bool Union(int x, int y){
    29     int a = Find(x);
    30     int b = Find(y);
    31     if(a==b) return 0;
    32     
    33     if(a > b){  // 小的赋值给大的集合号
    34         father[a] = b;
    35     }else{
    36         father[b] = a;
    37     }
    38     return true;
    39 }
    40 
    41 int Kruskal(int n){
    42     int ans = 0;
    43     for(int i=0; i<m; i++){
    44         if(Union(e[i].u, e[i].v)){
    45             ans += e[i].w;
    46             n--;
    47             if(n == 1)  // 我们要选n-1条边
    48                 return ans;
    49         }
    50     }
    51     return 0;
    52 }
    53 int main(){
    54     cout << "输入结点数n和边数m:" << endl;
    55     cin >> n >> m;
    56     Init(n);
    57     cout << "输入结点u,v和边权w:" << endl;
    58     for(int i=0; i<m; i++)
    59         cin >> e[i].u >> e[i].v >> e[i].w;
    60     sort(e, e+m, cmp);
    61     int ans = Kruskal(n);
    62     cout << "最小的化费是:" << ans << endl;
    63     int sum = 0;
    64     for(int i=1; i<=n; i++){
    65         cout << father[i] << " ";
    66         if(father[i] == i)
    67             sum++;
    68     }
    69     cout << endl;
    70     cout << "sum = " << sum << endl;
    71     return 0;
    72 }

     7 12

     1 2 23

     1 6 28

     1 7 36

     2 3 20

     2 7 1

     3 4 15

     3 7 4

     4 5 3

     4 7 9

     5 6 16

     5 7 16

     6 7 25

  • 相关阅读:
    290. Word Pattern
    283. Move Zeroes
    278. First Bad Version
    276. Paint Fence
    270. Closest Binary Search Tree Value
    [jobdu]二进制中1的个数
    [jobdu]丑数
    Skip List
    [wikioi]没有上司的舞会
    POJ3984 迷宫问题
  • 原文地址:https://www.cnblogs.com/JCcodeblgos/p/11524696.html
Copyright © 2011-2022 走看看