HELLO WORLD--一起加油(🍺|

kingwzun

园龄:3年6个月粉丝:111关注:0

2022-09-02 17:42阅读: 704评论: 0推荐: 2

扩展域并查集

扩展域并查集就是指:将并查集的状态由基本的:几个元素属于朋友,则放入并查集;
扩展为更多状态。

更多通过题目来理解把。

P2024 [NOI2001] 食物链

题意

动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。

A 吃 B,B 吃 C,C 吃 A。

现有 N 个动物,以 1∼N 编号。

每个动物都是 A,B,C 中的一种,但是我们并不知道它到底是哪一种。

有人用两种说法对这 N 个动物所构成的食物链关系进行描述:

第一种说法是 1 X Y,表示 X 和 Y 是同类。

第二种说法是 2 X Y,表示 X 吃 Y。

此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真的,有的是假的。

当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

当前的话与前面的某些真的话冲突,就是假话;
当前的话中 X 或 Y 比 N 大,就是假话;
当前的话表示 X 吃 X,就是假话。
你的任务是根据给定的 N 和 K 句话,输出假话的总数。

思路

可以将状态分为:
同类,食物,天敌
也就是说,将状态扩展为:

  • 同类:如果a和b是同一类,则将a和b合并到一个并查集

  • 食物:如果a是b的食物,则将a和b合并到一个并查集

  • 天敌:如果a是b的天敌,则将a和b合并到一个并查集

将状态扩展后,相应的合并也要修改。

  • 如果a和b是同类,那么
    a的天敌、同类、食物也是b的天敌、同类、食物。

  • 如果a是b的天敌,那么
    a的天敌是b的食物;
    a的同类是b的天敌;
    a的食物是b的同类。

然后再判断题目的几个条件

当前的话中 X 或 Y 比 N 大,就是假话;

直接判断即可

当前的话表示 X 吃 X,就是假话。

当输入为同类时,直接判断即可

当前的话与前面的某些真的话冲突,就是假话;

如果输入a是b的同类,那么需要确定以下条件,才能算对

  • a的天敌没有b
  • a的食物没有b

不需要判断:a的同类是不是b的同类

如果输入a是b的天敌,那么需要确定以下条件,才能算对

  • a的同类没有b
  • a的天敌没有b

不需要判断:a的食物是不是b的同类

实现

就是用3倍的并查积的存各种动物的关系:一倍存本身,二倍存食物,三倍存天敌。

每次维护三个并查积的关系就可以了
具体看代码吧

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
const int N =1e5 + 10;
int fa[N*3];
int n,m;
int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void slove()
{
cin>>n>>m;
for(int i=1;i<=3*n;++i) fa[i]=i;
int ans=0;
int x1, x2, x3, y1, y2, y3;
for(int i=1;i<=m;i++){
int a,x,y;cin>>a>>x>>y;
if(x>n || y>n){
ans++;
continue;
}
x1 = find(x);//同类
x2 = find(x + n);//食物
x3 = find(x + n * 2);//天敌
y1 = find(y);
y2 = find(y + n);
y3 = find(y + n * 2);
if(a==1){
//如果1是2的天敌或猎物,显然为谎言
if(x2==y1 || x3==y1){
ans++;
continue;
}
fa[x1]=y1 , fa[x2]=y2 , fa[x3]=y3;
}
else{
//如果1是2的同类或猎物,显然为谎言
if(x1==y1 || x3==y1){
ans++;
continue;
}
fa[x2] = y1 , fa[x3]=y2 , fa[x1]=y3;
}
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
slove();
return 0;
}

本文作者:kingwzun

本文链接:https://www.cnblogs.com/kingwz/p/16650762.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   kingwzun  阅读(704)  评论(0编辑  收藏  举报
历史上的今天:
2021-09-02 Java基础语法
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起