POJ 1182 食物链 [并查集 带权并查集 开拓思路]
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u
Description
现有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
以下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
先吐槽一下关于多组样例的问题,闲话也不多说,这题网上大牛各种神奇的题解都有,第一份代码是常规带权并查集的做法,不多谈,我主要想谈一下第二份代码的思路。
如果我们换一个思路,把1--n看成与自身同类的集合,1+n--2*n看成自己吃的集合,1+2*n--3*n看成吃自己的集合,那么问题便简单多了~~~
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<string> 12 13 #define N 50005 14 #define M 105 15 #define mod 1000000007 16 //#define p 10000007 17 #define mod2 1000000000 18 #define ll long long 19 #define LL long long 20 #define eps 1e-6 21 #define inf 100000000 22 #define maxi(a,b) (a)>(b)? (a) : (b) 23 #define mini(a,b) (a)<(b)? (a) : (b) 24 25 using namespace std; 26 27 int n,m; 28 int f[N]; 29 int r[N]; 30 int ans; 31 32 void ini() 33 { 34 ans=0; 35 int i; 36 for(i=0;i<=n;i++){ 37 f[i]=i; 38 r[i]=0; 39 } 40 } 41 42 int find(int x) 43 { 44 int fa; 45 if(f[x]!=x) 46 { 47 fa=find(f[x]); 48 r[x]=(r[x]+r[ f[x] ])%3; 49 f[x]=fa; 50 } 51 return f[x]; 52 } 53 54 void merge(int x,int y,int d) 55 { 56 int a,b; 57 a=find(x); 58 b=find(y); 59 if(a==b){ 60 return; 61 } 62 f[b]=a; 63 r[b]=(3-r[y]+r[x]+d)%3; 64 } 65 66 void solve() 67 { 68 int d,x,y; 69 int a,b; 70 int re; 71 int i; 72 for(i=1;i<=m;i++){ 73 scanf("%d%d%d",&d,&x,&y); 74 if(x>n || y>n){ 75 ans++;continue; 76 } 77 if(d==2 && x==y){ 78 ans++;continue; 79 } 80 a=find(x); 81 b=find(y); 82 re=(3-r[x]+r[y])%3; 83 if(a==b && re!=d-1){ 84 ans++;continue; 85 } 86 //printf(" i=%d\n",i); 87 merge(x,y,d-1); 88 } 89 } 90 91 void out() 92 { 93 printf("%d\n",ans); 94 } 95 96 int main() 97 { 98 //freopen("data.in","r",stdin); 99 //freopen("data.out","w",stdout); 100 //scanf("%d",&T); 101 //for(int ccnt=1;ccnt<=T;ccnt++) 102 //while(T--) 103 //while(scanf("%d%d",&n,&m)!=EOF) 104 scanf("%d%d",&n,&m); 105 { 106 ini(); 107 solve(); 108 out(); 109 } 110 return 0; 111 }
如果我们换一个思路,把1--n看成与自身同类的集合,1+n--2*n看成自己吃的集合,1+2*n--3*n看成吃自己的集合,那么问题便简单多了~~~
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<string> 12 13 #define N 50005 14 #define M 105 15 #define mod 1000000007 16 //#define p 10000007 17 #define mod2 1000000000 18 #define ll long long 19 #define LL long long 20 #define eps 1e-6 21 #define inf 100000000 22 #define maxi(a,b) (a)>(b)? (a) : (b) 23 #define mini(a,b) (a)<(b)? (a) : (b) 24 25 using namespace std; 26 27 int n,m; 28 int f[3*N]; 29 int ans; 30 31 void ini() 32 { 33 ans=0; 34 int i; 35 for(i=0;i<=3*n;i++){ 36 f[i]=i; 37 } 38 } 39 40 int find(int x) 41 { 42 int fa; 43 if(f[x]!=x) 44 { 45 fa=find(f[x]); 46 f[x]=fa; 47 } 48 return f[x]; 49 } 50 51 void merge(int x,int y) 52 { 53 int a,b; 54 a=find(x); 55 b=find(y); 56 if(a==b){ 57 return; 58 } 59 f[b]=a; 60 } 61 62 void solve() 63 { 64 int d,x,y; 65 int a,b; 66 int fx,sx; 67 int i; 68 for(i=1;i<=m;i++){ 69 scanf("%d%d%d",&d,&x,&y); 70 if(x>n || y>n){ 71 ans++;continue; 72 } 73 if(d==2 && x==y){ 74 ans++;continue; 75 } 76 a=find(x); 77 b=find(y); 78 fx=find(x+n); 79 sx=find(x+2*n); 80 if(d==1){ 81 if(b==fx || b==sx){ 82 ans++;continue; 83 } 84 else{ 85 merge(x,y); 86 merge(x+n,y+n); 87 merge(x+2*n,y+2*n); 88 } 89 } 90 else{ 91 if(b==a || b==sx){ 92 ans++;continue; 93 } 94 else{ 95 merge(x+n,y); 96 merge(x+2*n,y+n); 97 merge(x,y+2*n); 98 } 99 } 100 } 101 } 102 103 void out() 104 { 105 printf("%d\n",ans); 106 } 107 108 int main() 109 { 110 //freopen("data.in","r",stdin); 111 //freopen("data.out","w",stdout); 112 //scanf("%d",&T); 113 //for(int ccnt=1;ccnt<=T;ccnt++) 114 //while(T--) 115 //while(scanf("%d%d",&n,&m)!=EOF) 116 scanf("%d%d",&n,&m); 117 { 118 ini(); 119 solve(); 120 out(); 121 } 122 return 0; 123 }
转载于:https://www.cnblogs.com/njczy2010/p/4263305.html
POJ 1182 食物链 [并查集 带权并查集 开拓思路]相关推荐
- poj 1182 食物链(高级的带权并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 76486 Accepted: 22742 Description ...
- POJ 1984 Navigation Nightmare 【经典带权并查集】
任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS Memory Limit: 30000K To ...
- POJ 2492 A Bug's Life 带权并查集
题意: 思路: mod2 意义下的带权并查集 如果两只虫子是异性恋,它们的距离应该是1. 如果两只虫子相恋且距离为零,则它们是同性恋. (出题人好猥琐啊) 注意: 不能输入一半就break出来.... ...
- POJ 2492 A Bug's Life (带权并查集 向量偏移)
题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配 ...
- 学习笔记——拓展域并查集和带权并查集
1,拓展域并查集 一般的并查集只能查找出各元素之间是否存在某一种相同的联系,如:a和b是亲戚关系,b和c是亲戚关系,这时就可以查找出a和c也存在亲戚关系.但如果存在多种相对的联系时一般的并查集就不行了 ...
- 树形结构 —— 并查集 —— 带权并查集
[概述] 定义:带权并查集即是结点存有权值信息的并查集. 适用:当两个元素之间的关系可以量化,并且关系可以合并时,可以使用带权并查集来维护元素之间的关系. 权值:带权并查集每个元素的权通常描述其与并查 ...
- poj 1182 食物链 并查集
转自一位大佬的最全题解 https://blog.csdn.net/c0de4fun/article/details/7318642 #include <cstdio> #include ...
- 【POJ - 1703】Find them, Catch them(带权并查集之--种类并查集 权为与父节点关系)
题干: Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 36176 Accep ...
- POJ 2912 Rochambeau(难,好题,枚举+带权并查集)
下面的是从该网站上copy过来的,稍微改了一点,给出链接:http://hi.baidu.com/nondes/item/26dd0f1a02b1e0ef5f53b1c7 题意:有N个人玩剪刀石头布, ...
最新文章
- Java JDBC批处理插入数据操作
- 《LoadRunner 12七天速成宝典》—第2章2.1节开始
- 使用Eric构建Caffe应用程序-Baby年龄识别
- java http 返回码_【Java】Http返回状态码
- Android之android studio如何解决‘:app:packageDebug‘.(Duplicate files copied in APK META-INF/DEPENDENCIES)
- Qt creator5.7 OpenCV249之图片旋转(含源码下载)
- khv是什么虚拟服务器,服务器虚拟化vSphere4 vs Hyper-V R2,选择谁?
- 行政职业能力测试软件,公务员行政职业能力测试考试宝典
- Java中什么时候throws_何时在Java方法声明中使用throws?
- 《推荐系统笔记(六)》svd在推荐系统中的应用推广(FunkSVD,BiasSVD以及SVD++)及简单实战(surprise库)
- 数据库设计 表和表之间的三种关系
- 电商网站主动取消客户已支付成功订单感想
- rhel6+apache2.4+mysql5.7+php5.6部署LAMP架构
- 苹果笔记本能玩英雄联盟吗_英雄联盟手游要上线了,王者荣耀还会有人玩吗
- Android 原生插件开发步骤
- 小游戏————坦克大战
- Python自制“超级马里奥”小游戏
- python实现数字反转_python 数字怎么反转
- JavaScript中的“黑话” 1
- 【转】【转】 图像处理与计算机视觉的经典书籍
热门文章
- kdj超卖_一个判断股票超买超卖现象的指标——KDJ,简单明了,准确且省心
- 深入理解Java类加载器:Java类加载原理解析
- workman 使用心得
- Nginx下301重定向不带www的域名到带www的域名
- Web自动化测试 Selenium+Eclipse+Junit+TestNG+Python
- vue,一路走来(10)--生产环境
- poj 1077 Eight(A*)
- 如何设置SecureCRT通过代理连接SSH[转]
- 对比kCCPositionTypeFree和kCCPositionTypeRelative两种粒子移动类型
- 深入浅出BI——搭建环境