带权并查集(hdu 3635,hdu 2818)
2013-09-25 10:54
190 查看
带权并查集:
http://acm.hdu.edu.cn/showproblem.php?pid=3635
根据题意可得,我们要求某个球移动了多少次,一个城市有多少个球。
对于第二个问题很好解决,当我们用并查集并的时候,将子节点内的球全部赋给父节点,即num[parent]+=num[loof];
第一个问题才是大家纠结的。我们想一下,当将并查集的子节点连接到父节点时即表示子节点内的所有球都移动了一次,并查集最终形成的是一棵树,我们只需要求叶子节点到根节点的距离。叶子节点表示的是球开始的位置,根节点则是球现在所在的位置。这样我们就可以在并查集查原始父节点的时候来求,即每次都加上父节点到父节点的父节点的次数即可以求的。
hdu 2818
http://acm.hdu.edu.cn/showproblem.php?pid=2818
这题数据太坑,说了1~N的,结果包含了0,坑啊
这道题与POJ1988一样
http://poj.org/problem?id=1988
http://acm.hdu.edu.cn/showproblem.php?pid=3635
根据题意可得,我们要求某个球移动了多少次,一个城市有多少个球。
对于第二个问题很好解决,当我们用并查集并的时候,将子节点内的球全部赋给父节点,即num[parent]+=num[loof];
第一个问题才是大家纠结的。我们想一下,当将并查集的子节点连接到父节点时即表示子节点内的所有球都移动了一次,并查集最终形成的是一棵树,我们只需要求叶子节点到根节点的距离。叶子节点表示的是球开始的位置,根节点则是球现在所在的位置。这样我们就可以在并查集查原始父节点的时候来求,即每次都加上父节点到父节点的父节点的次数即可以求的。
#include <iostream> #include <cstdio> #include <cstring> #define MAX 10200 using namespace std; int parent[MAX],Rank[MAX],num[MAX]; int n,m,flag; void init() { for(int i=1; i<=n; i++) { Rank[i]=0; num[i]=1; parent[i]=i; } flag++; } int find(int x) { if(parent[x]!=x) { int temp=parent[x]; parent[x]=find(parent[x]); Rank[x]+=Rank[temp]; //每次加上父节点到父节点的父节点的次数 } return parent[x]; } void Union(int a,int b) { int root_a=find(a), root_b=find(b); if(root_a==root_b) return; parent[root_a]=root_b; num[root_b]+=num[root_a]; //子节点的球的全部放到根节点上 num[root_a]=0; //子节点 上的球个数为0 Rank[root_a]=1; //对于每个子节点,并一次即移动一次。 } void solve() { char ch[2]; int a,b; printf("Case %d:\n",flag); for(int i=1; i<=m; i++) { cin>>ch; if(ch[0]=='T') { cin>>a>>b; Union(a,b); } else { cin>>a; find(a); printf("%d %d %d\n",parent[a],num[parent[a]],Rank[a]); } } } int main() { int t; cin>>t; flag=0; while(t--) { cin>>n>>m; init(); solve(); } return 0; }
hdu 2818
http://acm.hdu.edu.cn/showproblem.php?pid=2818
这题数据太坑,说了1~N的,结果包含了0,坑啊
这道题与POJ1988一样
http://poj.org/problem?id=1988
#include <iostream> #include <cstring> #include <cstdio> #define MAX 30100 using namespace std; int parent[MAX],num[MAX],Rank[MAX]; int n; void init() { for(int i=0; i<MAX; i++) { parent[i]=i; num[i]=1; //表明树桩上有多少个石块 Rank[i]=0; //石块i下面有多少石块 } } int find(int x) { if(parent[x]!=x) { int temp=parent[x]; parent[x]=find(parent[x]); Rank[x]+=Rank[temp]; } return parent[x]; } void Union(int a,int b) { int root_a=find(a), root_b=find(b); if(root_a==root_b) return; parent[root_a]=root_b; Rank[root_a]=num[root_b]; //让连接到根节点的节点的值等于根节点上的石块数目,这样可以在查操作的时候更新每个石块下有多少石块 num[root_b]+=num[root_a]; //将所有子节点上的石块移动到根节点
num[root_a]=0;
} void solve() { char ch[2]; int a,b; for(int i=1; i<=n; i++) { cin>>ch; if(ch[0]=='M') { cin>>a>>b; Union(a,b); } else { cin>>a; find(a); printf("%d\n",Rank[a]); } } } int main() { while(cin>>n) { init(); solve(); } return 0; }
相关文章推荐
- HDU 3635 Dragon Balls(带权并查集)
- hdu 2818 Building Block (多个权值的并查集)
- HDU 2818 Building Block(带权并查集)
- HDU 3635 Dragon Balls(并查集)
- hdu 3635(并查集的应用)
- HDU 3635 Dragon Balls(带权并查集)
- HDU 3635 Dragon Balls(并查集)
- hdu 3635 并查集
- HDU 2818 Building Block 带权并查集
- hdu Dragon Balls 3635【并查集】
- hdu 2818 Building Block (带权并查集,很优美的题目)
- hdu 2818 Building Block(并查集)
- 【HDU】2818-Building Block(并查集)
- hdu 3635 Dragon Balls(并查集的各种应用)
- HDU 3635 Dragon Balls 带权并查集
- HDU 3635 Dragon Balls - 并查集
- hdu 3635 Dragon Balls (并查集,路径压缩应用)
- HDU 2818 Building Block【并查集+根节点偏移量】
- hdu 3635(并查集)
- hdu 3635 Dragon Balls 并查集