您的位置:首页 > 其它

食物链 带权并查集

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

①带权并查集

#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 );
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: