POJ 1182 食物链

本题让我感觉自己又菜了一等,叫苦不迭

链接:http://poj.org/problem?id=1182


参考大神文章:http://blog.csdn.net/niushuai666/article/details/6981689


并查集,不是一般的并查集,在父亲和儿子之间加了一层关系,1(同类),2(前者吃后者),这就比较尴尬了POJ 1182 食物链_第1张图片

用结构体来替换一般并查集的father数组,如

struct node
{
    int father;
    int relation;
} s[50002];
初始化结构体

for(int i=0; i<=n; i++)
    {
        s[i].father=i; //开始是父节点为本身
        s[i].relation=0; //与自己没什么关系,置零
    }
先排除题目中的2、3两种情况,直接判其为假:

1)当前的话中X或Y比N大,即x>n || y>n

2) 自己吃自己,即d==2 && x==y


之后查找父节点,比较重要的是更新关系域(s[i].relation)

再放一遍大神的文章:http://blog.csdn.net/niushuai666/article/details/6981689

其中的两个公式只看懂了”%3“是什么意思,我就不一本道了


还有:不需要写循环输入,写了WA;cin,cout超时

做的比较懵,还需要再理解一下(敬请指导)

#include <cstdio>
using namespace std;
struct node
{
    int father;
    int relation;
} s[50002];
int find(int n)
{
    if(s[n].father==n) return n;
    int t=s[n].father;
    s[n].father=find(t);
    s[n].relation=(s[n].relation + s[t].relation)%3;
    return s[n].father;
}
int main()
{
    int n,k;
    scanf("%d %d",&n,&k);
    int d,x,y,sum=0;
    for(int i=0; i<=n; i++)
    {
        s[i].father=i;
        s[i].relation=0;
    }
    while(k--)
    {
        scanf("%d %d %d",&d,&x,&y);
        if(x>n || y>n)
        {
            sum++;
            continue;
        }
        if(d==2 && x==y)
        {
            sum++;
            continue;
        }
        int rootx=find(x);
        int rooty=find(y);
        if(rootx!=rooty)
        {
            s[rooty].father=rootx;
            s[rooty].relation=(3+(d-1)+s[x].relation-s[y].relation)%3;
        }
        else
        {
            if(d==1 && s[x].relation!=s[y].relation)
            {
                sum++;
                continue;
            }
            if(d==2 && ((3-s[x].relation+s[y].relation)%3!=(d-1)))
            {
                sum++;
                continue;
            }
        }
    }
    printf("%d\n",sum);
    return 0;
}






你可能感兴趣的:(并查集,poj1182)