动物王国中有三类动物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句话有的是真的,有的是假的。

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

1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。

你的任务是根据给定的N和K句话,输出假话的总数。

输入格式

第一行是两个整数N和K,以一个空格分隔。

以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。

若D=1,则表示X和Y是同类。

若D=2,则表示X吃Y。

输出格式

只有一个整数,表示假话的数目。

数据范围

1≤N≤500001≤N≤50000,
0≤K≤1000000≤K≤100000

输入样例:

100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5

输出样例:

3

题解:

扩展域并查集:我们把每个动物拆成3个节点,分别是同类域xself,捕食域xeat,天敌域xenemy。

#include <iostream>
#include <cstdio> using namespace std; const int maxn = 3e5+; int f[maxn]; int get(int x) {
if(x == f[x]) {
return f[x];
}
int root = get(f[x]);
return f[x] = root;
} int main() {
int n, m;
scanf("%d %d", &n, &m);
for(int i = ; i <= * n; i++) {
f[i] = i;
}
int ans = ;
while(m--) {
int op, x, y;
scanf("%d %d %d", &op, &x, &y);
int x_self = x, x_eat = x + n, x_enemy = x + n + n;
int y_self = y, y_eat = y + n, y_enemy = y + n + n;
if(x > n || y > n) { //动物编号不存在
ans++;
} else if(op == ) { //x和y是同类关系
if(get(x_eat) == get(y_self) || get(x_self) == get(y_eat)) { //如果x捕食的物种和y的同类在同一集合,或者x的同类和y捕食的物种在同一集合,那么不成立,此话是假
ans++;
} else { //合并同类物种
f[get(x_self)] = get(y_self);
f[get(x_eat)] = get(y_eat);
f[get(x_enemy)] = get(y_enemy);
}
} else { //x和y是捕食关系,x吃y
if(get(x_self) == get(y_self) || get(x_self) == get(y_eat)) { //如果x的同类和y的同类在同一集合,或者x的同类和y捕食的物种在同一集合,那么不成立,此话是假
ans++;
} else { //合并同类物种
f[get(x_eat)] = get(y_self);
f[get(x_self)] = get(y_enemy);
f[get(x_enemy)] = get(y_eat);
}
}
}
printf("%d\n", ans);
return ;
}

带边权并查集:

看这篇优秀的博客,里面解释的很清楚:https://blog.csdn.net/linkfqy/article/details/69055713

#include <iostream>
#include <cstdio> using namespace std; const int maxn = 5e4+; int f[maxn];
int d[maxn]; int get(int x) {
if(x == f[x]) {
return f[x];
}
int root = get(f[x]);
d[x] += d[f[x]];
return f[x] = root;
} int main() {
int n, m;
scanf("%d %d", &n, &m);
int ans = ;
for(int i = ; i <= n; i++) {
f[i] = i;
d[i] = ;
}
while(m--) {
int x, y, w;
scanf("%d %d %d", &w, &x, &y);
if(x > n || y > n || (w == && x == y)) {
ans++;
continue;
}
int fx = get(x);
int fy = get(y);
if(fx == fy) {
if(((d[x] - d[y]) % + ) % != w - ) {
ans++;
}
} else {
f[fx] = f[fy];
d[fx] = d[y] + (w - ) - d[x];
}
}
printf("%d\n", ans);
return ;
}

最新文章

  1. csuoj 1394: Virus Replication
  2. Beta版本冲刺——day6
  3. Python内置的HTTP协议服务器SimpleHTTPServer
  4. Selenium脚本编写环境的搭建/XPath
  5. 阿里前CEO卫哲用自己10余年经历,倾诉B2B的三差、四率、两大坑
  6. U3D physics总结
  7. Apache网页有时能访问,有时超时打不开
  8. 转:DDR3详解(以Micron MT41J128M8 1Gb DDR3 SDRAM为例)之一
  9. 用IBM WebSphere DataStage进行数据整合: 第 1 部分
  10. js 前端操作的分页路由设计
  11. iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客
  12. GraphQL ---02 GraphQL和C#结合的实战项目
  13. 自定义 Cordova插件(基础篇)
  14. 面试回顾——List&lt;T&gt;排序
  15. CAD常用的快捷键命令
  16. cudnn升级之后caffe无法训练的问题
  17. Bluetooth_FTP_SPEC: 蓝牙FTP介绍
  18. Java Collection - 003 高效的找出两个List中的不同元素
  19. MYSQL如何解决幻读
  20. ubuntu16 intellij idea install lombok plugin

热门文章

  1. CodeFirst实体类中,为什么都把ICollection&lt;x&gt;定义成virtual?
  2. WinSockAPI多线程服务器
  3. C# enum枚举知识总结
  4. CSP-S2019「Symphony」
  5. BPM软件_K2再度入选Gartner iBPMS MQ挑战者象限_全球领先的工作流引擎
  6. SSISDB8:查看SSISDB记录Package执行的消息
  7. ssh-copy-id三步实现SSH无密码登录和ssh常用命令
  8. java lambda 所有列求和
  9. Flutter——Text组件(文字组件)
  10. linux安装vsftpd后无法登陆