poj 1182食物链(带权并查集)

食物链
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 60276   Accepted: 17671

Description

动物王国中有三类动物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

Source

Noi 01


思路:

  1.   0 - 这个节点与它的父节点是同类 
  2.   1 - 这个节点被它的父节点吃 
  3.   2 - 这个节点吃它的父节点

举个例子

a吃b, b吃c, c吃a, d吃c

吃法:  a->b->c-d

权值: 0->1->2->0

因为b的权值是1,所以b被他的根节点a吃, c的权值是2,所以c吃它的根节点a, d的权值是0,所以d跟它的根节点

同类



#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#include <map>
using namespace std;
#define esp  1e-8
const double PI = acos(-1.0);
const long long inf = 1000000000;
const long long mod = 10000007;
typedef long long LL;
#pragma comment(linker, "/STACK:1024000000,1024000000") 
//freopen("in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
int f[50005], v[50005];
int find(int x)
{
	if (x != f[x])
	{
		int u = f[x];
		f[x] = find(f[x]);
		v[x] = (v[x] + v[u]) % 3;
	}
	return f[x];
}
int main()
{
	int n, m, i, j;
	scanf("%d%d", &n, &m);//注意不要多组输入否则会wa
	{
		for (i = 0; i <= n; ++i)
			f[i] = i;
		memset(v, 0, sizeof(v));
		int ans = 0;
		while (m--)
		{
			int d, a, b;
			scanf("%d%d%d", &d, &a, &b);
			int fa = find(a);
			int fb = find(b);
			if (a > n || b > n || (a == b && d == 2))
			{
				ans++;
				continue;
			}
			if (fa == fb)
			{
				
				if ((v[a] != (v[b] + d- 1) % 3))
				{
					ans++;
					//continue;
				}
			}
			else
			{
				f[fa] = fb;//如果这里是f[fb] = fa的话,那么下面应该是v[fb] = (v[a] - v[b] + d - 1 + 3) % 3,上面应该是(v[b] != (v[a] + d- 1) % 3)
				//反正就是根节点的权值-子节点的权值
				v[fa] = (v[b] - v[a] + d - 1 + 3) % 3;
			}
		}
		printf("%d\n", ans);
	}
}



你可能感兴趣的:(poj 1182食物链(带权并查集))