【并查集】hdu 1213 How Many Tables
作者:互联网
题目描述:
http://acm.hdu.edu.cn/showproblem.php?pid=1213
中文大意:
朋友聚会,要求将直接或间接认识的人安排在一个桌子上,问最少需要几张桌子。
思路:
一个桌子就是一个集合。若 x y 为朋友关系,则将二者所在的集合合并。
数组 pre[] 记录的是节点的所属集,根节点的所属集 pre[x] = x;
代码:
#include<bits/stdc++.h> using namespace std; int n,m; int pre[1001];//各节点的所属集 int height[1001];//各集合的树高,用来做优化 //初始化,每个节点属于独立的集合 void init(){ for(int i=1;i<=n;i++){ pre[i] = i; height[i] = 1; } } //查询节点 x 的所属集 int find(int x){ //寻找根节点 int root = x; while(root != pre[root]){ root = pre[root]; } //路径压缩:将路径上节点的所属集改为根节点 int i = x; while(pre[i] != root){ int j = pre[i]; pre[i] = root; i = j; } return root; } //合并(优化后) void union_set(int x, int y){ //查询节点 x 的所属集 x = find(x); //查询节点 y 的所属集 y = find(y); //若两个集合的树高相同,则将 x 的所属集并到 y 的所属集 if(height[x] == height[y]){ height[y]++; pre[x] = y; }//否则,矮树并到高树上,并且高树的树高保持不变 else if(height[x] > height[y]){ pre[y] = x; } else{ pre[y] = x; } } int main(){ int t; scanf("%d", &t); while(t--){ scanf("%d %d", &n, &m); init(); int x,y; for(int i=0;i<m;i++){ scanf("%d %d", &x, &y); union_set(x, y); } //统计集合数量 int num = 0; for(int i=1;i<=n;i++){ if(pre[i] == i){ num++; } } printf("%d\n", num); } }
标签:pre,Tables,hdu,1213,int,scanf,height,集合,节点 来源: https://www.cnblogs.com/bjxqmy/p/14479551.html