食物链 带权并查集
2017-04-10 16:33
162 查看
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是”1 X Y”,表示X和Y是同类。
第二种说法是”2 X Y”,表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。
Input
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
Output
只有一个整数,表示假话的数目。
Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3
①带权并查集
②参考:http://blog.csdn.net/shadowcw/article/details/52159262
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是”1 X Y”,表示X和Y是同类。
第二种说法是”2 X Y”,表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。
Input
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
Output
只有一个整数,表示假话的数目。
Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3
①带权并查集
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define maxn 50005 #define mem(a, b) memset(a, b, sizeof(a)) struct Node { int pre, relation; //0同类,1表示吃父结点,2表示被父结点吃 } fa[maxn]; int n, k; int Find(int x) { if (fa[x].pre == x) return x; int tmp = Find(fa[x].pre); fa[x].relation = (fa[x].relation + fa[fa[x].pre].relation) % 3; return fa[x].pre = tmp; } int main() { scanf("%d%d", &n, &k); int ans = 0; for (int i = 1; i <= n; i++) { fa[i].pre = i; fa[i].relation = 0; } while (k--) { int d, x, y; scanf("%d%d%d", &d, &x, &y); if (d == 2 && x == y || x > n || y > n) { ans++; continue; } int fx = Find(x), fy = Find(y); if (fx == fy) { if ((fa[x].relation - fa[y].relation + 3) % 3 != d - 1) { ans++; } } else { int relation = (fa[y].relation + d - 1 - fa[x].relation + 3) % 3; fa[fx].pre = fy; fa[fx].relation = relation; } } printf("%d\n", ans); }
②参考:http://blog.csdn.net/shadowcw/article/details/52159262
#include <iostream> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <algorithm> #include <queue> #include <set> #define MST(s,q) memset(s,q,sizeof(s)) #define INF 0x3f3f3f3f #define MAXN 50005 #define Lchild id<<1 #define Rchild (id<<1)+1 inline int lowbit(int x) {return x & (-x);} using namespace std; int N, M, D, X, Y, ans = 0, F[MAXN * 3]; int find(int x) { if (F[x] == x) return x; return F[x] = find(F[x]); } bool same(int x, int y) { return find(x) == find(y); } void Union(int x, int y) { F[find(x)] = find(y); } int main() { cin >> N >> M; for (int i = 1; i < MAXN * 3; i++)F[i] = i; while (M--) { scanf("%d%d%d", &D, &X, &Y); if (X > N || Y > N || (D == 2 && X == Y)) ans++; else { if (D == 1) { if (same(X, Y + N) || same(X, Y + 2 * N)) { ans++; continue; } Union(X, Y); Union(X + N, Y + N); Union(X + 2 * N, Y + 2 * N); } else if (D == 2) { if (same(X, Y) || same(X, Y + 2 * N)) { ans++; continue; } Union(X, Y + N); Union(X + N, Y + 2 * N); Union(X + 2 * N, Y); } } } printf("%d\n", ans ); }
相关文章推荐
- 【并查集】POJ 1182 食物链
- POJ 1182 食物链 加权并查集
- poj 1182:食物链(种类并查集,食物链问题)
- POJ1182 食物链 (并查集)*新方法
- POJ 1182 食物链 并查集 + 权值
- POJ 1182 食物链 并查集
- 食物链 并查集扩展域
- 【洛谷2024】食物链 并查集
- CODEVS-1074-食物链-并查集
- [并查集]食物链
- POJ ~ 1182 ~ 食物链 (带权并查集)
- [置顶] POJ 1182 食物链(并查集) 详解
- 食物链-并查集
- POJ 1182 食物链 (种类并查集)
- pku 1182 食物链(并查集)
- poj 食物链(种类并查集)(思路)
- 【POJ 1182 食物链】并查集
- [POJ 1182]食物链[并查集]
- POJ - 1182 食物链 并查集经典
- 并查集应用 —— POJ 1182 食物链