食物链

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 94930   Accepted: 28666

Description:

动物王国中有三类动物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(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。

Input:

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

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

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

Output:

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

Sample Input:

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

Sample Output:

3

题解:

这题用并查集来做,可以从两个角度来思考,一是普通的并查集,另一个是带权并查集。

先说第一种,我们知道这是一个环状结构,A->B->C->A,题目中判断一句话是否为假话就是看是否与前面的冲突。我们可以这么考虑,开三个集合,表示种类A,B,C,由于目前我们现在不知道x,y属于哪个种类,所以在合并集合的时候都考虑一下(利用几个集合来维护之间的关系)。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std; const int N = ;
int f[N];
int n,k,ans; int find(int x){return f[x]==x ? x : f[x]=find(f[x]);} bool same(int x,int y){
return find(x)==find(y);
} void Union(int x,int y){
int fx=find(x),fy=find(y);
f[fx]=fy;
} int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=*n+;i++) f[i]=i;
while(k--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(x< || y< ||x>n ||y>n){
ans++;continue ;
}
int fx=find(x),fy=find(y);
if(op==){
if(same(x,y+n) ||same(x,y+*n)){
ans++;continue;
}
Union(x,y);Union(x+n,y+n);Union(x+*n,y+*n);
}else{
if(same(x,y) || same(x,y+*n)){
ans++;continue ;
}
Union(x,y+n);Union(x+n,y+*n);Union(x+*n,y);
}
}
printf("%d",ans);
return ;
}

再来说带权并查集。

我们用个数组r表示当前结点与父节点的关系,由于这是个环状关系,所以关系是可以传递的,比如r[p]=1代表p吃q,r[q]=1代表q吃z,那么p与z的关系就是z吃p,合并父亲后即是r[p]=2。

具体r的定义以及代码细节可以自己思考一下怎么处理(我想了几十分钟/伤心)

代码如下:

//带权并查集
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std; const int N = 5e4+;
int f[N],r[N]={};
int n,k,ans=; int find(int x){
if(f[x]==x) return x;
int tmp = f[x];
f[x]=find(f[x]);
r[x]=(r[x]+r[tmp])%;
return f[x];
} int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n+;i++) f[i]=i;
while(k--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(x< || y>n ||x>n ||y<){ans++;continue ;}
int fx=find(x),fy=find(y);
if(fx==fy){
if((r[x]-r[y]+)%!=op-) ans++;
}else{
f[fy]=fx;
if(op==) r[fy]=(r[x]+(-r[y]))%;
else r[fy]=(r[x]+(-r[y])+op);
}
}
printf("%d",ans);
return ;
}

POJ1182:食物链(并查集)的更多相关文章

  1. POJ-1182 食物链 并查集(互相关联的并查集写法)

    题目链接:https://cn.vjudge.net/problem/POJ-1182 题意 中文题目,就不写了哈哈 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃 ...

  2. [poj1182]食物链(并查集+补集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 64841   Accepted: 19077 Description ...

  3. POJ-1182 食物链---并查集(附模板)

    题目链接: https://vjudge.net/problem/POJ-1182 题目大意: 中文题,不多说. 思路: 给每个动物创建3个元素,i-A, i-B, i-C i-x表示i属于种类x,并 ...

  4. poj1182食物链--并查集

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

  5. POJ1182 食物链 并查集

    #include<iostream>#include<stdio.h>#include<string.h>using namespace std;const int ...

  6. 编程算法 - 食物链 并查集 代码(C)

    食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种 ...

  7. 【poj1182】食物链--并查集扩展域

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 109341   Accepted: 33191 Description 动物 ...

  8. POJ-1182 分组并查集

    今天刚发现,之前做的并查集只是贴模板基本就能过,题意改变一点,自己还是不懂,其实我还没入门呢... 题意:食物链,A吃B,B吃C,C吃A,输入m组数据: 1 a b:a 和 b 是同一类 2 a b: ...

  9. POJ 1182 (经典食物链 /并查集扩展)

    (參考他人资料) 向量偏移--由"食物链"引发的总结 http://poj.org/problem?id=1182这道食物链题目是并查集的变型.非常久曾经做的一次是水过的,这次 ...

随机推荐

  1. 第一个python代码

    # -*- coding:utf-8 -*- user = raw_input("请输入用户名") passwd = raw_input("请输入密码") if ...

  2. python2.7练习小例子(十六)

    16):题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数.     程序分析:利用 while 或 for 语句,条件为输入的字符不为 '\n'.     程序源代码: #!/u ...

  3. c# string.format和tostring()

    字符 说明 示例 输出 C 货币 string.Format("{0:C3}", 2) $2.000 D 十进制 string.Format("{0:D3}", ...

  4. Java:详解内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  5. 使用LinqToExcel和EPPlus操作excel

    1.使用LinqToExcel LinqToExcel是一个.net framework平台下开源项目,它主要实现了LINQ的语法查询Excel电子表格.类型之前的LINQToXXX如果你是LINQ语 ...

  6. js鼠标事件相关知识

    1.mousedown->mouseup依次触发后相当于click事件 2.除了mouseenter和mouseleave外,其它的鼠标事件都是冒泡的 3.mouseover和mouseout事 ...

  7. jmeter3.2版本如何进行webservice接口功能测试

    jmeter3.2版本之后就没有SOAP/XML-RPC Request插件了,所以没办法直接进行webservice接口的测试. 原理上: Web service一般就是用SOAP协议通过HTTP来 ...

  8. Linux-Shell脚本编程-学习-8-函数

    在这章往后的学习中,我讲尽可能详细的讲书中讲到的都记录到这里,以便以后方便查看. 什么是函数,函数就是一段代码,这段代码可以在我们需要的位置调用,那么这段代码就叫做函数. 在Shell中,定义一个函数 ...

  9. 第四篇 Python循环

    While 循环 For 循环

  10. POJ 3565 Ants(最佳完美匹配)

    Description Young naturalist Bill studies ants in school. His ants feed on plant-louses that live on ...