您的位置:首页 > 其它

POJ 1182 食物链

2015-11-03 15:37 260 查看
这是一道经典的并查集

类似线段树的区间更新,更新时不要更新到底层,查找时再更新

用有向距离表示关系,dis(a, b)为a到b的距离

令d = dis(a, b),注意:dis(a, b) = ( 3 - dis(b, a) ) % 3

d = 0 :a 与 b 同类

d = 1 :a 吃 b

d = 2 :b 吃 a

fa[i] : i 的父结点

dis[i] = dis(fa[i], i)

注意find函数的作用,find(n):更新dis
,fa
,返回n的根结点

更新完毕后,fa
是n所对应的根结点,故dis
为根结点到n的有向距离

高维也能类似解决

#include <cstdio>

int fa[50005], dis[50005];

int find(int n)
{
if(fa
!= n)
{
int t = find(fa
);
dis
= (dis
+ dis[fa
]) % 3;
fa
= t;
}
return fa
;
}

int main()
{
int n, k;
scanf("%d%d", &n, &k);

for(int i = 1; i <= n; i++)
fa[i] = i, dis[i] = 0;

int cnt = 0;
for(int i = 0; i < k; i++)
{
int op, a, b;
scanf("%d%d%d", &op, &a, &b);

if(a > n || b > n) {cnt++; continue;}
if(op == 2 && a == b) {cnt++; continue;}

int x = find(a), y = find(b);
int d = op - 1;

if(x == y)
{
if(dis[b] % 3 != (dis[a] + d) % 3)
cnt++;
continue;
}

fa[y] = x;
dis[y] = (dis[a] - dis[b] + d + 3) % 3;
}

printf("%d", cnt);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: