poj p1182解题报告(带权并查集)

是中文题意   我就不赘述了(源代码在下面  压代码压得很厉害,不要吐槽)

13778373nailer1182Accepted568K250MSC++798B2015-01-13 17:50:18

通过总结网上的大神的解释  我总结了一篇笔记(以食物链为例,花了两节自习课,真是呵呵了)

我们用D-1(也就是输入中所给的1,2)表示x对y的关系

也就是  x和y同类     0

              x吃y             1

             x被y吃          2

假如我们设ty,tx为y,x的爹

那么通过列表我们可以得到如下的结论(其中TYPE 为0时x,y同类;为1时,x吃y)

type 0 0 0 0 1 1 1 1 1                    
delta[x] 0 0 0 1 0 1 2 2 1                    
delta[y] 0 1

2

2 2 2 1 2 1                    
delta[ty] 0 2 1 2 2 0 2 1 1

tx       ty

         |

     y

之后我们可以得到如下代码(上面的那个表可以用笔来划一划,画成如上图一个类似矩形的玩意,标上方向更有利于下文的理解)

void link(int x,int y)

{

     fa[ty]=tx;

     d[ty]=(d[x]-d[y]+3+d-1)%3;

}

根据题目 我们知道一共只有3类动物  那么x,y一定存在着某种联系(来自poj的discuss),并且并查集中的一定有某种联系,不然并进来干吗?

那么我们可以用向量的知识来解答这道题

如果x->y的偏移量是0时    x,y是同类

如果x->y的偏移量是1时    x吃y

如果x->y的偏移量是2时    x被y吃

之后任意给出的两元素的关系便可以计算了

我们先分一下类

1  tx!=ty(ty和tx并无关系)

 tx->ty = tx->x + x->y + y->ty(向量思想)

  那么只需要把x,y按要求合并即可

2  ty==tx

  x->y=x->tx+tx->y=x->tx+ty->y

那么x->y = (3-deltx[x]+deltx[y])%3

上述的值如果和d-1一致则为真  否则为假

好了好了,就这样了下面是源代码(不要纯抄)

  #include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;


//nailertt
int d[50010],fa[50010],x,y,f,ty,tx,ans=0,n,m;
int nailerfind(int x){
if(fa[x]!=x){int od=fa[x];fa[x]=find(fa[x]);d[x]=(d[x]+d[od])%3;}
return fa[x];}
void nailerbuild(int n){for(int i=1;i<=n;i++){fa[i]=i;d[i]=0;}}
void nailerlink(int x,int y){fa[ty]=tx;d[ty]=(d[x]-d[y]+3+f-1)%3;}
int solve(int f,int x,int y){
if(x>n||y>n){return 1;}
ty=find(y),tx=find(x);
if(f==1&&x==y){return 1;}
if(tx==ty){
   if(f!=((3-d[x]+d[y])%3))return 1;
   else return 0;
}
if(tx!=ty){
link(x,y);return 0;
}
}
int main()
{
scanf("%d%d",&n,&m);
build(n);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&f,&x,&y);
ans+=solve(f-1,x,y);
}
printf("%d",ans);
return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值