并查集+向量偏移

poj 1182 食物链(并查集+向量偏移)

分类: ACM之并查集   157人阅读  评论(0)  收藏  举报
这道食物链实在让我纠结了好久。。。poj <wbr>1182 <wbr>食物链(并查集+向量偏移) 看别人的代码都看了好久。这里涉及到一种并查集的处理方法——向量偏移。同时有位大牛告诉我这种方法的本质就是要体会一句话:“陈冠希是谢霆锋情人的情人...谢霆锋是男人,所以陈冠希也是男人。”
这道题不单纯是查找根节点和合并节点,在处理的同时还要记录节点之间的关系。
这个博客让我明白了,向量偏移的方法。有图有真像哦!!!
http://hi.baidu.com/tomspirit/blog/item/fb8c5bd1a4c9552e960a16e1.html
这是我最开始理解并查集看的文章,写的很形象。
http://www.cnblogs.com/ACShiryu/archive/2011/09/17/union.html
(1)(2)向量图
#include<stdio.h>
struct node
{
 int parent;
 int relation;
}p[50010];//每个节点记录了它的父亲节点和此节点对当前所在集合的根节点的关系 
int find(int x)
{
    int t;
    if(p[x].parent==x) return x;
    else
    {
        t=p[x].parent;//记录未更新时候的父亲节点 
        p[x].parent=find(t);//继续查找根节点 
        p[x].relation=(p[t].relation+p[x].relation)%3;//更新此节点对根节点的关系(1) 
    }
    return p[x].parent;
}
void join(int x,int y,int r1,int r2,int d)
{
     p[r1].parent=r2;//r1的父亲节点指向r2 
     p[r1].relation=(3+d-1+p[y].relation-p[x].relation)%3;//更新关系(2)
//d-1 是因为relation 0 1 2代表同类 吃 和被吃 而 题中是1同类 2吃
}
int main()
{
    int n,k,i,num,r1,r2,d,x,y;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;i++)//初始化 
    {
     p[i].parent=i;
     p[i].relation=0;
    }
    num=0;
    while(k--)
    {
     scanf("%d%d%d",&d,&x,&y);
     if(x>n||y>n||(d==2&&x==y))  num++;
     //如果编号大于最大编号或者x吃y并且x,y同类则此话为假话 
     else
     {
         r1=find(x);
         r2=find(y);
         if(r1!=r2)//如果根节点不同那么就合并 
         join(x,y,r1,r2,d);
         else//如果根节点相同则判断x,y到根节点的关系进而判断是否是假话 
         {
             if(d==1&&p[x].relation!=p[y].relation) num++;//(3)
             else if(d==2&&(p[x].relation-p[y].relation+3)%3!=1) num++;//(4)
         }
     }
    }
    printf("%d",num);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值