并查集
Codeforces Round #692 C题:并查集
之前学过,现在全忘了,重学qwq
并查集:合并+查找
查找:找到某一个节点的祖先
合并:将题给的两个点(或是两个点集)合并
中间可以压缩路径
模板代码:
1 int parent[100] = {-1}; //初始化 2 int deep[100] = {0}; //初始化 3 4 int find_parent(int x) //查找 5 { 6 int x_root=x; 7 while(parent[x_root]!=-1) 8 x_root = parent[x_root]; 9 return x_root; 10 } 11 12 int union_disjoint(int x,int y) //合并 13 { 14 int x_root=find_parent(x); 15 int y_root=find_parent(y); 16 if(x_root==y_root) 17 return 1; //找到一个环 18 //不压缩:parent[x_root] = y_root; 19 if(deep[x_root]>deep[y_root]) //路径压缩 20 parent[y_root]=x_root; 21 if(deep[y_root]>deep[x_root]) 22 parent[x_root] = y_root; 23 if(deep[y_root]==deep[x_root]){ 24 parent[x_root] = y_root; 25 deep[y_root]++; 26 } 27 return 0; 28 }
模板题:
这里需要先排序(对时间代价),再用并查集
AC代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 6 int parent[1005]; 7 int deep[1005]; 8 struct node{ 9 int x; 10 int y; 11 int t; 12 } p[100005]; 13 14 bool com(struct node a,struct node b) 15 { 16 if(a.t<b.t) 17 return true; 18 else 19 return false; 20 } 21 22 int find_parent(int k) 23 { 24 int k_root = k; 25 while(parent[k_root]!=-1) 26 k_root = parent[k_root]; 27 return k_root; 28 } 29 30 31 int main() 32 { 33 int n, m; 34 int num = 1; 35 int x_root; 36 int y_root; 37 cin >> n >> m; 38 for (int i = 1; i <= n;i++){ 39 parent[i] = -1; 40 deep[i]=0; 41 } 42 for (int i = 1; i <= m;i++) 43 cin >> p[i].x >> p[i].y >> p[i].t; 44 sort(p + 1, p + m + 1, com); 45 for (int i = 1; i <= m;i++){ 46 x_root = find_parent(p[i].x); 47 y_root = find_parent(p[i].y); 48 if(x_root==y_root){ 49 continue; 50 }else{ 51 num++; 52 if(deep[x_root]>deep[y_root]) 53 parent[y_root] = x_root; 54 if(deep[x_root]<deep[y_root]) 55 parent[x_root] = y_root; 56 if(deep[x_root]==deep[y_root]){ 57 parent[x_root] = y_root; 58 deep[y_root]++; 59 } 60 } 61 if(num==n){ 62 cout << p[i].t; 63 return 0; 64 } 65 } 66 cout << -1; 67 return 0; 68 }
还有一道类似的题:洛谷P1195:口袋的天空
洛谷这两道题都先用了一个排序,后来查了一下,发现:
排序+并查集=Kruskal算法(目前感觉是这样,还没遇到其它的题,还是题刷的太少)
说到Kruskal算法,那就谈到了最小生成树(把并查集所得的树加上权值)
其实洛谷的两道题都是在求最小生成树
Prim算法(不会)和Kruskal算法是求最小生成树的两种算法
日常补题还是可以学到很多的

浙公网安备 33010602011771号