题目来自
JZYZOJ1697 食物链
其实这道题在思维上是有很大的困难的,我在做这道题时也是写写
画画很久才能理解这题的思维。所以这道题我也就不说为什么了。直接说做法
并查集对没有错就是并查集
查找、合并的过程与普通并查集没什么差别。
我们定义
\(f[i]\)是同类
\(f[i+n]\)吃\(i\)
\(f[i+2*n]\)被\(i\)吃
紧接着就是判断
int a,b;
if(getfather(a) == getfather(b))//a b 同类
if(getfather(a) == getfather(b+n))// a 吃 b
if(getfather(a) == getfather(b+2*n)) // b 吃 a
通过这个方法来判断每局话真假就好
coding
#include <bits/stdc++.h>
using namespace std;
const int N = 150015;
int n,k,cnt = 0,fa[3*N] = {},d,a,b;
inline int read()
{
register int x = 0;
register char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9')
{
x = (x<<3)+(x<<1) + ch-'0';
ch = getchar();
}
return x;
}
inline int getfather(int x)
{
if(x == fa[x]) return x;
return fa[x] = getfather(fa[x]);
}
inline void bing(int x,int y)
{
x = getfather(x); y = getfather(y);
fa[x] = y;
}
int main()
{
n = read(); k = read();
for(register int i = 1;i <= 3*n;i++) fa[i] = i;
for(;k >= 1;k--)
{
d = read(); a = read(); b = read();
if(a > n || b > n || (d == 2 && a == b))
{
cnt++;
continue;
}
if(d == 1)
{
if(getfather(a+n) == getfather(b) || getfather(a+2*n) == getfather(b))
{
cnt++;
continue;
}
bing(a,b); bing(a+n,b+n); bing(a+2*n,b+2*n);
}
else
{
if(getfather(a) == getfather(b) || getfather(a+n) == getfather(b))
{
cnt++;
continue;
}
bing(a+2*n,b); bing(a+n,b+2*n); bing(a,b+n);
}
}
printf("%d\n",cnt);
return 0;
}