食物链
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),输出假话的总数。
现有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。
以下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
思路:
- 0 - 这个节点与它的父节点是同类
- 1 - 这个节点被它的父节点吃
- 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);
}
}