• 并查集


    概念:

      并:合并两个元素所在的组

      查:查询两个元素是否属于同一个组

    核心代码: 

     1 int par[MAX_N];        //父节点
     2 int rank[MAX_N];    //树的高度
     3 
     4 //初始化
     5 void init(int n)
     6 {
     7     for(int i = 0; i < n; i++)
     8     {
     9         par[i] = i;    //初始时一个树一个节点
    10         rank[i] = 0;
    11     }
    12 }
    13 
    14 //查询树的根
    15 int find(int x)
    16 {
    17     if(par[x] == x)
    18     {
    19         return x;
    20     }
    21     else
    22     {
    23         return par[x] = find(par[x]);    //递归 依次查询
    24     }
    25 }
    26 
    27 //合并x和y所属的集合
    28 void unite(int x, int y)
    29 {
    30     x = find(x);    //x的根
    31     y = find(y);    //y的根
    32 
    33     if(x == y)    //同一个根节点
    34     {
    35         return;
    36     }
    37     if(rank[x] < rank[y])        //从高度小的往高度大的合并
    38     {
    39         par[x] = y;
    40     }
    41     else
    42     {
    43         par[y] = x;
    44         if(rank[x] == rank[y])    //相等 rank++
    45             rank[x]++;
    46     }
    47 }
    48 
    49 //判断x和y是否同属于一个集合
    50 int same(int x, int y)
    51 {
    52     return find(x) == find(y);
    53 }

    例题:

      题目链接:http://codeforces.com/gym/100989/problem/B

      题意:

        给定dp[]数组,它描述的是两个字符串a[]与b[]的关系情况。要求根据dp[]数组推出a[]与b[]。

        dp[]数组所描述关系:

     1 function LCS (A[1..R], B[1..C])
     2     DP = array(0..R, 0..C)
     3     for i := 0..R
     4        DP[i,0] = 0
     5     for j := 0..C
     6        DP[0,j] = 0
     7     for i := 1..R
     8         for j := 1..C
     9             if A[i] = B[j]
    10                 DP[i,j] := DP[i-1,j-1] + 1
    11             else
    12                 DP[i,j] := max(DP[i,j-1], DP[i-1,j])
    13     return DP[R,C]

      思路:

        并查集在这里的运用是,将a[]数组中与b[]数组中相等的元素合并在一棵树,再根据合并情况给两字符串赋值。

        val_trees[]将a[]与b[]中相同的合并在一棵树,然后依次小到大对不在一棵树上的a[]赋值,max_ch记录当前最

        大字符,然后再依次判断b[]中元素是否与a[]中的元素在一棵树上。是的话,把相等的那个字符赋值给它,不

        然就赋值为max_ch+1的那个字符(与a[]不存在相等关系的元素们可以是不同字符也可以是相同字符)。而且

        a[]中是允许有相同的元素的,比如a[1]=b[2]=a[3]之类的。

      代码:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 const int MAXN = 32;
     6 
     7 int dp[MAXN][MAXN], val_trees[MAXN * 2];
     8 char a[MAXN], b[MAXN];
     9 
    10 int root(int i)
    11 {
    12     return val_trees[i] == i ? i : val_trees[i] = root(val_trees[i]);
    13 }
    14 
    15 int main(const int argc, const char *argv[])
    16 {
    17     int la, lb;
    18     char max_ch = 'a';
    19 
    20     cin >> la >> lb;
    21 
    22     for (int i = 0; i < la + lb; i++)
    23     {
    24         val_trees[i] = i;
    25     }
    26 
    27     for (int i = 0; i <= la; i++)
    28         for (int j = 0; j <= lb; cin >> dp[i][j++]);
    29 
    30     for (int i = 0; i < la; i++)
    31     {
    32         for (int j = 0; j < lb; j++)
    33         {
    34             int dp_temp = dp[i + 1][j + 1];
    35             if (dp_temp != dp[i][j + 1] && dp_temp != dp[i + 1][j])
    36             {
    37                 val_trees[root(la + j)] = root(i);
    38             }
    39         }
    40     }
    41 
    42     for (int i = 0; i < la; i++)
    43     {
    44         if ((a[i] = root(i) + 'a') > max_ch)
    45         {
    46             max_ch = a[i];
    47         }
    48     }
    49     max_ch++;
    50 
    51     for (int i = 0; i < lb; i++)
    52     {
    53         int ia = root(la + i);
    54         b[i] = ia < la ? a[ia] : max_ch;
    55     }
    56 
    57     cout << a << endl << b << endl;
    58 
    59     return 0;
    60 }
  • 相关阅读:
    C#开发微信公众平台-就这么简单(附Demo)
    Newtonsoft.Json高级用法
    C#获取文件的MD5码
    C#动态执行代码
    c#插件式开发
    利用反射执行代码
    yield关键字用法与解析(C# 参考)
    HttpContext.Current.Cache和HttpRuntime.Cache的区别,以及System.Runtime.Caching
    GZip压缩与解压缩
    Asp.Net 请求处理机制
  • 原文地址:https://www.cnblogs.com/friend-A/p/9293405.html
Copyright © 2020-2023  润新知