POJ 1703 1182 2492 一类并查集题目-(类别偏移量)
2012-08-09 20:18
375 查看
转自http://blog.chinaunix.net/space.php?uid=23709303&do=blog&id=2388866
poj 1182
题意为有三类动物,他们的食物链是环,即 A 吃 B, B 吃 C, C 吃 A。
给出一些动物的食物链关系,根据以前的关系,判断当前关系是否正确。
因为并查集是一棵森林,我们用一个数组 dist[i] 记录并查集的树中结点 i 与根的关系, 值为 1 表示吃根结点, 2 表示被根结点吃,为 0 表示两者为同一类动物。
对于输入的关系 d x y :
1). 如果 x, y 属于同一集合,判断两都关系是否合理,根据下图:
x, y 为同一集合, 所以 x, y 指向同一根。 x 与根 rt 的关系距离为 dist[x], y 与根 rt 的关系距离为 dist[y],
根据输入 x 与 y 的关系距离为 d。 由图有 d+ dist[y]== dist[x] ( mod 3 )。
2). 如果 x, y 不属于同一集合,根据下图有:
图中 x 与 rx 属同一集合,rx 的 x 的根, y 与 ry 原同一集合,ry 为 y 的根。 rx!= ry, x 与 y 不属于同一集合,这时应当将 x, y 合并,这里合并时将 rx 指向 ry, ry 成了新集合的根,根据图有:
d+ dist[y]== dist[x]+ dist[rx] --> dist[rx]= d+ dist[y]- dist[x] 求出了关系距离。
还有一个问题(就上图而言): x 与 y 合并后, ry 成了新集合的根,这时原来以 rx 为根的集合中的结点与 ry 的关系距离需要重新确定,如何确定:
假设并查集树为 x->a->b->rx ->ry, rx->ry 的关系距离已经求出,即 dist[rx] 已知, b 到 ry 的关系距离为 b 到 rx 的距离加上 rx 到 ry 的距离和。 故 dist[b]= dist[b]+ dist[rx]。 依次求出。
其中1182 最有代表性这里给出代码
另外两题还可以用一种简单的分组的思想,p[x]代表和x一类的,p[x + n]代表和x异类的,但应用范围很窄,这里贴上1703
poj 1182
题意为有三类动物,他们的食物链是环,即 A 吃 B, B 吃 C, C 吃 A。
给出一些动物的食物链关系,根据以前的关系,判断当前关系是否正确。
因为并查集是一棵森林,我们用一个数组 dist[i] 记录并查集的树中结点 i 与根的关系, 值为 1 表示吃根结点, 2 表示被根结点吃,为 0 表示两者为同一类动物。
对于输入的关系 d x y :
1). 如果 x, y 属于同一集合,判断两都关系是否合理,根据下图:
x, y 为同一集合, 所以 x, y 指向同一根。 x 与根 rt 的关系距离为 dist[x], y 与根 rt 的关系距离为 dist[y],
根据输入 x 与 y 的关系距离为 d。 由图有 d+ dist[y]== dist[x] ( mod 3 )。
2). 如果 x, y 不属于同一集合,根据下图有:
图中 x 与 rx 属同一集合,rx 的 x 的根, y 与 ry 原同一集合,ry 为 y 的根。 rx!= ry, x 与 y 不属于同一集合,这时应当将 x, y 合并,这里合并时将 rx 指向 ry, ry 成了新集合的根,根据图有:
d+ dist[y]== dist[x]+ dist[rx] --> dist[rx]= d+ dist[y]- dist[x] 求出了关系距离。
还有一个问题(就上图而言): x 与 y 合并后, ry 成了新集合的根,这时原来以 rx 为根的集合中的结点与 ry 的关系距离需要重新确定,如何确定:
假设并查集树为 x->a->b->rx ->ry, rx->ry 的关系距离已经求出,即 dist[rx] 已知, b 到 ry 的关系距离为 b 到 rx 的距离加上 rx 到 ry 的距离和。 故 dist[b]= dist[b]+ dist[rx]。 依次求出。
其中1182 最有代表性这里给出代码
#include <stdio.h> #include <stdlib.h> const int N= 50010; int n, k; int uset , dist ; int find( int x ){ if( x== uset[x] ) return x; int rt= find( uset[x] ); dist[x]= ( dist[x]+ dist[ uset[x] ] )% 3; uset[x]= rt; return rt; } FILE* fp = fopen("in.txt", "r"); int main(){ fscanf(fp, "%d%d",&n,&k); for( int i= 0; i<= n; ++i ){ uset[i]= i; dist[i]= 0; } int ans= 0; for( int i= 0; i< k; ++i ){ int d, x, y; fscanf(fp, "%d%d%d", &d, &x, &y ); if( x> n || y> n || (x == y && d == 2)){ ans++; continue; } d--; int rx= find(x), ry= find(y); if( rx== ry ){ if( ( d+ dist[y] )% 3 != dist[x] % 3 ) ans++; }else{ uset[rx]= ry; dist[rx]= ( d+ dist[y]- dist[x]+ 6 )% 3; } } printf("%d\n", ans ); getchar(); return 0; }
另外两题还可以用一种简单的分组的思想,p[x]代表和x一类的,p[x + n]代表和x异类的,但应用范围很窄,这里贴上1703
#include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define N 100009 int p[N * 2]; int find(int x){return p[x] == x? x : p[x] = (find(p[x]));} int main() { int t, n, m; //FILE* fp = fopen("in.txt", "r"); fscanf(fp,"%d", &t); while (t--) { fscanf(fp, "%d %d", &n, &m); for (int i = 1; i <= 2 * n; i++)p[i] = i; char s[3]; int a, b; for (int i = 0; i < m; i++) { fscanf(fp,"%s %d %d", s, &a, &b); int x1 = find(a), y1 = find(a + n); int x2 = find(b), y2 = find(b + n); if (s[0] == 'D') { p[y1] = x2; p[y2] = x1; } else { if (x1 != x2 && y1 != x2)puts("Not sure yet."); else if (x1 == x2)puts("In the same gang."); else puts("In different gangs."); } } } getchar(); return 0; }
相关文章推荐
- poj 1703 , hdu 1729 , poj 1182 并查集偏移量应用
- POJ 1703 1182 2492 并查集 偏移
- hdu - 1829 A Bug's Life (并查集)&&poj - 2492 A Bug's Life && poj 1703 Find them, Catch them
- 一类并查集问题( POJ 1182 )
- 并查集(poj1611、2524、2492、1182)
- POJ 1182 食物链(种类并查集 + 偏移量)
- poj 1703 poj 2492 并查集 桥梁判AB组
- POJ1703 && POJ2942 &&POJ 1182 并查集 这个做法挺巧妙
- 【带偏移量的并查集】:poj2492,A Bug's Life
- Poj 1703 / Poj 1182 并查集二题
- poj 2492 A Bug's Life(带类别偏移并查集)
- POJ 1703 POJ 2492 并查集 和 食物链差不多
- POJ 1703 && poj 1182【典型并查集】
- POJ 2492 A Bug's Life(种类并查集 + 偏移量)
- POJ 2492 A Bug's Life 并查集维护类别
- 并查集初学(4)向量思维 POJ1182(食物链)&& POJ1703
- poj--1703/2492 (经典并查集)
- POJ 1182 1703 并查集的应用
- poj 1703 Find them, Catch them(带偏移量并查集)
- 《挑战程序设计竞赛》2.4 数据结构-并查集 POJ1182 2236 1703 AOJ2170