NOI 2009 食物链

题目来自

JZYZOJ1697 食物链

Luogu P2024 [NOI2001]食物链


其实这道题在思维上是有很大的困难的,我在做这道题时也是写写
画画很久才能理解这题的思维。

所以这道题我也就不说为什么了。直接说做法

并查集对没有错就是并查集

查找、合并的过程与普通并查集没什么差别。

我们定义
\(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;
}

猜你喜欢

转载自www.cnblogs.com/Mark-X/p/11699525.html