您的位置:首页 > 其它

poj1182(食物链)----带权并查集

2016-07-23 11:19 253 查看
这道题,刚开始开了3个并查集,各种关系把我搞得头晕,已提交就是wa,怎么也找不出错误,上网查题解发现是并查集姿势不对!!!

只需开一个并查集,只要能确定关系就扔进并查集里,其中每个元素与老大哥的关系无非三种:同类,被吃,吃人,分别用0,1,2来表示。

那么每来一次判断,先判断两个是否有关系,没关系就肯定是真话,join;

否则就得判断是否说谎;

d==1且ta与tb是同类,没说谎

d==2且ta与tb满足

三种可能

ta tb

0 1

1 2

2 0

合起来就是(rt[tb]-rt[ta]+3)%3==1)

那么没说谎

其余情况都是说谎。

下一个难点就是join函数

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

(d==2) rt[fx]=(rt[y]-rt[x]+2)%3;

按照上面那种思路就可以得出,不懂的话可以看一些其他blog

http://blog.csdn.net/c0de4fun/article/details/7318642

http://wxdlut.blog.163.com/blog/static/128770158200982754311269/

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <string.h>
#include <queue>
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
int pre[50005],rt[50005];//0表示pre[x]和x同类,1表示x被吃,2表示x吃人
int fnd(int node)
{
if(pre[node]==node) return node;
int tmp=pre[node];
pre[node]=fnd(pre[node]);
rt[node]=(rt[tmp]+rt[node])%3;
return pre[node];
}
void join(int x,int y,int d)
{
int fx=fnd(x),fy=fnd(y);
if(fx!=fy) pre[fx]=fy;
if(d==1) rt[fx]=(rt[y]-rt[x]+3)%3;
else rt[fx]=(rt[y]-rt[x]+2)%3;
}
int main(int argc, char const *argv[])
{
int n,k,cnt=0;
cin>>n>>k;
int d,ta,tb;
ms(rt);
for(int i=1;i<=n;i++) pre[i]=i;
while(k--)
{
scanf("%d %d %d",&d,&ta,&tb);
if(ta>n||tb>n||(ta==tb&&d==2)) {cnt++;continue;}
if(fnd(ta)==fnd(tb)){
if(d==1&&rt[ta]==rt[tb]) continue;
else if(d==2&&(rt[tb]-rt[ta]+3)%3==1) continue;
else cnt++;
}
else join(ta,tb,d);
}
printf("%d",cnt );
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj