POJ 1182 解题报告
2014-11-20 04:30
288 查看
这道题似乎是union-find的经典题目。
这道题我在捕食关系上面弄得很乱,(改改说不定能弄对),最后看了discuss上面一个同学的解法写的,最后和这个同学的代码就一模一样了:http://poj.org/showmessage?message_id=344806
大致理解为:对任意一个编号为i的动物,它能捕食的动物集合和N+i都是一个集合的, 捕食它的动物集合和2N+i是一个集合的。这样总的集合大小为3N,编号为0~3N-1。好处是理解比较清晰。
判断两个动物(X, Y)可不可能是同一个类型的,只需要比较下Y和X捕食的动物或捕食X的动物在不在一个集合里面就可以了。如果可能是一个类型的,那就是真话,把X,Y放到一个集合里面,同时, X+N和Y+N,以及X+2N和Y+2N也要并起来。
判断两个动物(X,Y)是不是X能够捕食Y,也比较清晰。即看Y是不是和X或者捕食X的动物在一个集合里面。如果不能的话,那么X是可能会捕食Y的。这样,把X和捕食Y的放在一个集合里面。同理,把捕食X的和Y捕食的并起来,把X捕食的和Y并起来。
这道题我在捕食关系上面弄得很乱,(改改说不定能弄对),最后看了discuss上面一个同学的解法写的,最后和这个同学的代码就一模一样了:http://poj.org/showmessage?message_id=344806
大致理解为:对任意一个编号为i的动物,它能捕食的动物集合和N+i都是一个集合的, 捕食它的动物集合和2N+i是一个集合的。这样总的集合大小为3N,编号为0~3N-1。好处是理解比较清晰。
判断两个动物(X, Y)可不可能是同一个类型的,只需要比较下Y和X捕食的动物或捕食X的动物在不在一个集合里面就可以了。如果可能是一个类型的,那就是真话,把X,Y放到一个集合里面,同时, X+N和Y+N,以及X+2N和Y+2N也要并起来。
判断两个动物(X,Y)是不是X能够捕食Y,也比较清晰。即看Y是不是和X或者捕食X的动物在一个集合里面。如果不能的话,那么X是可能会捕食Y的。这样,把X和捕食Y的放在一个集合里面。同理,把捕食X的和Y捕食的并起来,把X捕食的和Y并起来。
1182 | Accepted | 1796K | 297MS | G++ | 2178B |
/* ID: thestor1 LANG: C++ TASK: poj1182 */ #include <iostream> #include <fstream> #include <cmath> #include <cstdio> #include <cstring> #include <limits> #include <string> #include <vector> #include <list> #include <set> #include <map> #include <queue> #include <stack> #include <algorithm> #include <cassert> using namespace std; int findset(int X, std::vector<int> &parent) { if (parent[X] != X) { parent[X] = findset(parent[X], parent); } return parent[X]; } void unionset(int X, int Y, std::vector<int> &parent, std::vector<int> &rank) { int rx = findset(X, parent); int ry = findset(Y, parent); if (rx == ry) { return; } if (rank[rx] < rank[ry]) { parent[rx] = ry; } else if (rank[ry] < rank[rx]) { parent[ry] = rx; } else { parent[rx] = ry; rank[ry]++; } } int main() { // std::ios::sync_with_stdio(false); int N, K; // cin >> N >> K; scanf("%d%d", &N, &K); std::vector<int> parent(3 * N); std::vector<int> rank(3 * N); for (int i = 0; i < 3 * N; ++i) { parent[i] = i; rank[i] = 0; } int nlies = 0; for (int i = 0; i < K; ++i) { int D, X, Y; // cin >> D >> X >> Y; scanf("%d%d%d", &D, &X, &Y); if (X < 1 || Y < 1 || X > N || Y > N) { nlies++; continue; } if (X == Y) { if (D == 2) { nlies++; } continue; } X--, Y--; // int rx = findset(X, parent); int ry = findset(Y, parent); // X and Y are the same group if (D == 1) { if (findset(X + N, parent) == ry || findset(X + 2 * N, parent) == ry) { nlies++; } else { unionset(X, Y, parent, rank); unionset(X + N, Y + N, parent, rank); unionset(X + 2 * N, Y + 2 * N, parent, rank); } } else { // X eats Y assert (D == 2); if (findset(X, parent) == ry || findset(X + 2 * N, parent) == ry) { nlies++; } else { unionset(X, Y + 2 * N, parent, rank); unionset(X + N, Y, parent, rank); unionset(X + 2 * N, Y + N, parent, rank); } } } // cout << nlies << endl; printf("%d\n", nlies); return 0; }
相关文章推荐
- 【POJ1182】食物链,思路+数据+代码,可能是史上关于这道题最详细的解题报告
- POJ 1182 食物链 -- 解题报告
- POJ 1182 并查集 解题报告
- poj 1182-食物链解题报告
- 【原创】poj ----- 1182 食物链 解题报告
- poj1182解题报告
- poj 1182 食物链(并查集)解题报告(转)
- POJ1182 食物链 ACM解题报告(并查集+路径压缩难题)
- POJ1182 解题报告
- 【解题报告】 POJ 1182 食物链 并查集的经典应用+相对位置
- poj 1182 食物链(并查集)解题报告(转)
- POJ-1182-食物链 解题报告
- poj解题报告——1182
- poj 1182 食物链 解题报告
- POJ-2553-The Bottom of a Graph 解题报告
- POJ 1830 开关问题 解题报告(高斯消元法)
- POJ 2689 Prime Distance 解题报告(素数筛)
- POJ 2429 GCD & LCM Inverse 解题报告(大数因式分解)
- POJ 2004解题报告
- Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告