概念:
并:合并两个元素所在的组
查:查询两个元素是否属于同一个组
核心代码:
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 }