思路①:

开数组enem[i]记录节点i的敌对节点,当再次输入i的敌对节点时就把他所在并查集的根节点和enem[i]并起来。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e4+7;
const int INF = 1e9+7;
int n,m;
int fa[maxn];
int enem[maxn];//i的敌人是enem[i]
int find(int x)
{if(fa[x] == x) return x;fa[x]=find(fa[x]);return fa[x];
}
void Union(int x,int y)
{int r1=find(x),r2=find(y);if(r1 == r2) return;fa[r1]=r2;
}
int main()
{scanf("%d %d",&n,&m);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++){char ch;int a,b;scanf(" %c %d %d",&ch,&a,&b);if(ch=='F') Union(a,b);else {if(!enem[a]) enem[a]=find(b);else Union(b,enem[a]);if(!enem[b]) enem[b]=find(a);else Union(a,enem[b]);}}int count[maxn]={0},ans=0;for(int i=1;i<=n;i++) count[find(i)]++;//错误: 写成count[f[i]]++for(int i=1;i<=n;i++) {if(count[i]) ans++;}cout<<ans;return 0;
}

思路②:先假设i必定存在敌人i+n 后面如果遇到i的敌人就把他和i+n并起来。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e3+7;
const int INF = 1e9+7;
int n,m;
int fa[maxn];
//利用反集 令a+n为a的敌人 后面遇到新敌人b就把b和a+n并起来,最终利用a+n把a的所有敌人并起来了
int find(int x)
{if(fa[x] == x) return x;fa[x]=find(fa[x]);return fa[x];
}
void Union(int x,int y)
{int r1=find(x),r2=find(y);if(r1 == r2) return;fa[r1]=r2;
}
int main()
{scanf("%d %d",&n,&m);for(int i=1;i<=2*n;i++) fa[i]=i;for(int i=1;i<=m;i++){char ch;int a,b;scanf(" %c %d %d",&ch,&a,&b);if(ch=='F') Union(a,b);else {Union(a+n,b);//注意这里是把a+n的根节点设为b 这样下面统计根节点才不会出错Union(b+n,a);}}int ans=0;for(int i=1;i<=n;i++){if(fa[i]==i) ans++;}cout<<ans;return 0;
}

这题的两种思路其实都是一样的,关键就是获得i的第一个敌人的编号,后面遇到的敌人就与第一个敌人并起来。

食物链

这题比上一题要复杂一些,多了一种关系,不过还是可以用同一种思路,

我们开三个并查集 分别维护: 同类, 吃, 被吃。
对于任意一个动物a ,我们令a吃a+n , a+2n吃a
a
↓ ↖
a+n→a+2*n
箭头表示吃

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
const int maxn = 5e4+7;
const int INF = 1e9+7;
//有三种动物 共n只 满足a吃b b吃c c吃a   给出m句话描述关系 输出假话数目
//思路:开三个并查集 分别维护 同类 吃 被吃  对于每个动物a  a吃a+n  a+2n吃a
int n,m;
int fa[maxn*3];
int find(int x)
{if(fa[x] == x) return x;fa[x]=find(fa[x]);return fa[x];
}
void Union(int x,int y)
{int r1=find(x),r2=find(y);if(r1 == r2) return;fa[r1]=r2;
}
bool same(int x,int y)
{if(find(x) == find(y)) return 1;return 0;
}
int main()
{scanf("%d %d",&n,&m);for(int i=1;i<=n*3;i++) fa[i]=i;int ans=0;while(m--){int k,x,y;scanf("%d %d %d",&k,&x,&y);if(x<1 || x>n || y<1 || y>n) {ans++;continue;}if(k == 1)//x y 同类{if(same(x,y+n) || same(x,y+2*n))//存在捕食关系,是假话{ans++;}else//是真话{Union(x,y);Union(x+n,y+n);Union(x+2*n,y+2*n);}}else //x 吃 y, 相当于x和y+2n是一个集合的{if(same(x,y+n) || same(x,y))//x被y吃 xy同类{ans++;}else {Union(x,y+2*n);Union(x+n,y);Union(x+2*n,y+n);}}}cout<<ans<<'\n';return 0;
}

P1892 [BOI2003]团伙 +食物链 POJ - 1182 (并查集+思维)相关推荐

  1. 精讲并查集经典习题:P1892 [BOI2003]团伙(超详细)

    一,需要开o2才能AC的代码 用emys[i]存储第i个人的敌人数,vector<long long>emyr[i]存储i个人的所以敌人,fa[i]存储第i个人的大boss. 1.初始化  ...

  2. C - 食物链 POJ - 1182

    C - 食物链 POJ - 1182 大佬,%%% 加入给你一个 1, 那 1 应该放进 A.B.还是C呢,不知道了,所以开三倍的空间, 1~n 表示 A, n+1~2n 表示 B, 2n+1 ~ 3 ...

  3. P1892 [BOI2003]团伙(反集)

    P1892 [BOI2003]团伙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 现在有 nn 个人,他们之间有两种关系:朋友和敌人.我们知道: 一个人的朋友的朋友是朋友 ...

  4. 食物链 POJ - 1182(带权并查集模板)

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种 ...

  5. 洛谷 P1892 [BOI2003]团伙(并查集变种 反集)

    [BOI2003]团伙 题目描述 现在有 n n n 个人,他们之间有两种关系:朋友和敌人.我们知道: 一个人的朋友的朋友是朋友 一个人的敌人的敌人是朋友 现在要对这些人进行组团.两个人在一个团体内当 ...

  6. P1892 [BOI2003]团伙(并查集,反集)难度⭐⭐★

    题目链接 反集 如果a和b是敌人,合并n+b和a,n+a和b 如果c和a是敌人,合并n+c和a,n+a和c 那么b和c自然就合并在一起了 这样就符合了题目敌人的敌人是朋友的规则 注意 并查集不要忘了初 ...

  7. 食物链 poj 1182

    C - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  8. 洛谷P1892 [BOI2003]团伙

    链接:P1892 题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友. 两 ...

  9. 食物链 POJ - 1182

    题目: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有 ...

最新文章

  1. Android性能优化 - 内存优化
  2. arduino绘图_如何使用Arduino构建绘图仪
  3. 【LeetCode】剑指 Offer 40. 最小的k个数
  4. 栈的数据结构特点(小白基础)
  5. 利用E4A编写APP获取安卓手机加速度传感器数据
  6. dp 母函数 入门 + 模板
  7. 博弈论与信息经济学-重复博弈
  8. 【Python网络爬虫】实战#181024
  9. 炼气化神——信源编码之定乾坤
  10. 什么是BCD码以及区分二进制与BCD码
  11. proteus仿真-单片机-超声波测距报警
  12. 【转】解决 Office 2007/2010 安装错误:1402
  13. 测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
  14. 【Word】删除页眉底部横线
  15. 将端到端文本转语音速度提高38倍,全新语音合成系统FastSpeech 梅尔谱的生成速度提升270倍,微软和浙大联合推出
  16. 诚信迎考 计算机考试主题班会策划,关于诚信考试的主题班会
  17. shell脚本 java jar_linux下shell脚本执行jar文件
  18. 电脑c盘备份怎么操作?备份C盘的6个步骤
  19. MIUI12查看Android版本,MIUI12新功能与支持机型一览 开发版内测申请教程
  20. Linux内核巨页代码解析和使用

热门文章

  1. Dockerfile构建新镜像--网易蜂巢--RHEL7.2
  2. 【C++】构造函数与析构函数
  3. layui element tab 无法切换(tab偶尔能切换,偶尔不行,踩的一个坑)
  4. C语言之四书五经—C语言书籍推荐
  5. js实现密度单位转换代码怎么写
  6. 多用户 php源码_PHP多用户网络日记(青春日记) v1.0
  7. Win10 steam版战地3战役无限初始化解决方案汇总
  8. 知识分子的傲慢与偏见 (2012-08-18 00:50:57)
  9. 《西游记之大圣归来》
  10. DoraCloud云教室实践