poj1703(各种姿势)

题目链接:http://poj.org/problem?id=1703

题意:有n个人分别属于两个团伙,接下来m组形如 ch, x, y的数据,ch为“D"表示 x, y属于不同的团伙,ch为"A"表示询问x,y书否属于同一个团伙;

解法1:我们可以用jion(x, y)属于同一个团伙,jion(x+n, y)表示x属于第二个团伙,y属于第一个团伙,jion(x, y+n)表示x属于第一个团伙,y属于第二个团伙;

那么对于每组不同团伙的x, y我们只需要jion(x+n, y) ,jion(x, y+n)即可;查询时判断x,y或者x+n, y+n根节点是否相同即可,因为集合关系jion表示属于同一团伙,根节点相同则属于相同团伙,若x, y+n,或者x+n, y根节点相同则属于不同团伙,其余情况即为不能确定;

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define MAXN (100000+10)  //***MAXN后面做下标时MAXN*2,要加括号,不然会越界!!run time error!!!
 5 using namespace std;
 6
 7 int pre[MAXN*2], rank[MAXN*2]; //***rank用来区分树的高度,但其不存储树的具体高度
 8
 9 int find(int x){
10     int r = x;
11     while(pre[r]!=r){
12         r = pre[r];
13     }
14     int i = x;      //****路径压缩
15     while(pre[i]!=r){
16         int gg = pre[i];
17         pre[i] = r;
18         i = gg;
19     }
20     return r;
21 }
22
23 void jion(int x, int y){
24     int xx = find(x);
25     int yy = find(y);
26     if(rank[xx]>rank[yy]){   //***启发式合并,就是把矮的树合并到高的树地下,把合并时间从0(n)降到o(logn)
27         pre[yy] = xx;
28     }else{
29         pre[xx] = yy;
30         if(rank[xx] == rank[yy]){ //**若树的标记高度一样,那么给合并后作为父亲的树rank+1,以区分树的高度
31             rank[xx]++;
32         }
33     }
34 }
35
36 int main(void){
37     int t;
38     scanf("%d", &t);
39     while(t--){
40         int n, m;
41         scanf("%d%d", &n, &m);
42         for(int i=1; i<=2*n; i++){
43             pre[i] = i;
44             rank[i] = 0;
45         }
46         while(m--){
47             char ch[2];
48             int x, y;
49             scanf("%s%d%d", ch, &x, &y);
50             if(ch[0]==‘D‘){
51                 jion(x, y+n);
52                 jion(x+n, y);
53             }else{
54                 if(find(y+n)==find(x)||find(x+n)==find(y)){
55                     printf("In different gangs.\n");
56                 }else if(find(x)==find(y)||find(x+n)==find(y+n)){
57                     printf("In the same gang.\n");
58                 }else{
59                     printf("Not sure yet.\n");
60                 }
61             }
62         }
63     }
64     return 0;
65 }

方法2:用vis数组标记不同的集合,如:vis[x]=y,表示与x不同集合的点y;

用并查集合并属于同一类的点集;

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #define MAXN 100010
 4 using namespace std;
 5
 6 int pre[MAXN], vis[MAXN], rank[MAXN]; //***vis标记不同集合的编号,rank区分树高
 7 //***vis[x]=y,表示记录x与y不同集合,相当于无向图,所以需双向标记
 8
 9 /*int find(int x){  //**400+ms
10     int r = x;
11     while(pre[r]!=r){
12         r = pre[r];
13     }
14     int i = x;
15     while(i!=r){
16         int gg = pre[i];
17         pre[i] = r;
18         i = gg;
19     }
20     return r;
21 }*/
22
23 int find(int x){ //**306ms (再加启发式合并=282ms)
24     return pre[x]==x ? x : pre[x] = find(pre[x]);
25 }
26
27 void jion(int x, int y){
28     int xx = find(x);
29     int yy = find(y);
30     if(rank[xx] > rank[yy]){
31         pre[yy] = xx;
32     }else{
33         pre[xx] = yy;
34         if(rank[xx] == rank[yy]){
35             rank[yy]++;
36         }
37     }
38 }
39
40 int main(void){
41     int t;
42     scanf("%d", &t);
43     while(t--){
44         int n, m;
45         scanf("%d%d", &n, &m);
46         for(int i=1; i<=n; i++){
47             pre[i] = i;
48             vis[i] = 0;
49             rank[i] = 0;
50         }
51         while(m--){
52             char ch[2];
53             int x, y;
54             scanf("%s%d%d", ch, &x, &y);
55             if(ch[0]==‘D‘){
56                 if(vis[x]==0 && vis[y]==0){  //**x, y都没出现过
57                     vis[x] = y;
58                     vis[y] = x;
59                 }else if(vis[x]==0){ //**x没出现过
60                     vis[x] = y;
61                     jion(x, vis[y]);
62                 }else if(vis[y]==0){ //**y没出现过
63                     vis[y] = x;
64                     jion(y, vis[x]);
65                 }else{               //**都出现过
66                     jion(x, vis[y]);
67                     jion(y, vis[x]);
68                 }
69             }else{
70                 if(find(x)==find(y)){
71                     printf("In the same gang.\n");
72                 }else if(find(x)==find(vis[y])){
73                     printf("In different gangs.\n");
74                 }else{
75                     printf("Not sure yet.\n");
76                 }
77             }
78         }
79     }
80     return 0;
81 }

方法3:

种类并查集,先区分能不能辨别的情况,然后只要考虑同和不同两种情况,可以用rank数组记录当前节点x与其根节点是否相同的信息,1表相同,0表不同;

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #define MAXN 100010
 4 using namespace std;
 5
 6 int pre[MAXN], rank[MAXN]; //**rank储存x与x的根节点是否相同的信息,1表相同,0表不同
 7
 8 int find(int x){
 9     if(x==pre[x]){
10         return pre[x];
11     }
12     int xx = pre[x];
13     pre[x] = find(pre[x]);
14     rank[x] = (rank[x] + rank[xx])&1; //**压缩路径,x的根节点改变了,rank[x]也要改变
15     return pre[x];
16 }
17
18 void jion(int x, int y){
19     int xx = find(x);
20     int yy = find(y);
21     if(xx!=yy){
22         pre[yy] = xx;
23         rank[yy] = (rank[x] + rank[y] + 1)&1; //**合并只需改变yy之前的rank值
24     }
25 }
26
27 int main(void){
28     int t;
29     scanf("%d", &t);
30     while(t--){
31         int n, m;
32         scanf("%d%d", &n, &m);
33         for(int i=1; i<=n; i++){
34             pre[i] = i;
35             rank[i] = 0;
36         }
37         while(m--){
38             char ch[2];
39             int x, y;
40             scanf("%s%d%d", ch, &x, &y);
41             if(ch[0]==‘D‘){
42                 jion(x, y);
43             }else{
44                 if(find(x)==find(y)){
45                     if(rank[x]==rank[y]){
46                         printf("In the same gang.\n");
47                     }else{
48                         printf("In different gangs.\n");
49                     }
50                 }else{
51                     printf("Not sure yet.\n");
52                 }
53             }
54         }
55     }
56     return 0;
57 }
时间: 2024-08-05 08:02:43

poj1703(各种姿势)的相关文章

程序员取悦女朋友的正确姿势---Tips(iOS美容篇)

前言 女孩子都喜欢用美图工具进行图片美容,近来无事时,特意为某人写了个自定义图片滤镜生成器,安装到手机即可完成自定义滤镜渲染照片.app独一无二,虽简亦繁. JH定律:魔镜:最漂亮的女人是你老婆魔镜:程序员不是木头人 核心技术 图片滤镜核心技术的基本思路如下: 核心技术流程 具体流程 1.创建一个图像处理工具类 注:该类实例包括一个图像处理方法,该方法在传入原始图像和一个颜色矩阵后生成一个处理好的图像. @interface JHFeilterManager : NSObject @proper

算法分析的正确姿势

[本系列博文会对常见的数据结构及相应算法进行分析与总结,并会在每篇博文中提供几道相关的一线互联网企业面试/笔试题来巩固所学及帮助我们查漏补缺.项目地址:https://github.com/absfree/Algo.由于个人水平有限,叙述中难免存在不清晰准确的地方,希望大家可以指正,谢谢大家:)] 一.前言 在进一步学习数据结构与算法前,我们应该先掌握算法分析的一般方法.算法分析主要包括对算法的时空复杂度进行分析,但有些时候我们更关心算法的实际运行性能如何,此外,算法可视化是一项帮助我们理解算法

Android开发必知--使用View.setId的正确姿势

这两天在写一个柱状图的自定义控件,用的直接继承ViewGroup的方式实现的,我们都知道,这是自定义控件里面最简单的一种了,有时间写个总结分享一下.这里我想说的重点是,在写这个自定义控件的时候遇到了个关于View.setId()小问题,在网上查了好多,有很多回答真是纯属扯淡,最后终于在stackoverflow上找到了零零碎碎的解决方案,stackoverflow真是一个好地方,几乎所有的问题都可以在上面找到解决方案.在此对这个问题整理记录下来,以便参考. 其实这个问题也应该是一个开发者必须提前

【bzoj3224】Tyvj 1728 普通平衡树 平衡树的三种姿势 :splay,Treap,ScapeGoat_Tree

直接上代码 正所谓 人傻自带大常数 平衡树的几种姿势:  AVL Red&Black_Tree 码量爆炸,不常用:SBT 出于各种原因,不常用. 常用: Treap 旋转 基于旋转操作和随机数堆 但不支持区间操作. 非旋转 基于随机数堆和拆分合并操作 常数较大 Spaly 完全基于旋转 各种操作 ScapeGoat_Tree 基于a权值平衡树和压扁重构 无旋转 但不支持区间操作 PS:非旋转可以实现平衡树的可持久化,从而来套一些东西 splay #include<cstdio> #de

1+1=0.5的姿势困局!谁让美丽蘑菇的合并泛起泡沫

自从2016年1月,美丽说.蘑菇街正式合并以来,裁员风声就没断过.但这并不重要.重要的是,较之其他如滴滴快的.新美大之类的同领域执牛耳者的合并,不再火并.合并后的美丽说.蘑菇街只能用惨淡来形容. 从合并前2015年两家交易额合计近200亿元,到2016年合并后交易额90亿元左右,1+1=0.5的状态,让许多业界观察者唏嘘不已. 文/张书乐(TMT行业观察者.游戏产业时评人,人民网.人民邮电报专栏作者) 刊载于<互联网经济>2017年4月刊 为何会如此?两家公司尽管是同领域中执牛耳者,但这个准确

架构师米洛:你不经意的职场坏姿势会损坏你的身体

老祖宗经常教育我们:要站如松坐如钟.培养正确的身体姿势,会让你更有气质笔挺站立,你会显得更高挑. 同时姿势还会影响别人对你的看法,肩膀挺直坐着的人,看上去放松而且充满自信,瘫坐在椅子上的人看起来懒散.冷淡.有距离感.职场上坐姿端正的人总会让人感觉更加有气派. 好姿势可以提升骨骼健康当你瘫坐时,多余的压力都集中在脖子和脊椎上,时间久了,可能产生轻微的背部疼痛:不良的走姿.跑姿容易使关节磨损,脊椎也会因此受到来自四面八方的"坏压力",从而压迫神经和血管. 好姿势能让内脏"松口气&

iOS 创建对象的姿势

在写 ios开发中,怎么样去 new 一个新对象出来,都有一些讲究在里面.使用不同的姿势去创建对象,对后期维护所造成的影响会存在细微的差别. init 创建 在之前一篇分析 iOS 代码耦合的文章中,提到过当我们给一个对象的 property 赋值的时候,通过 init方法传入参数来初始化 property 会让我们的代码更可靠. 有些人在定义带 property 的 class 的时候,会这样定义: @interface User : [email protected] (nonatomic,

网秦Q3财报现新姿势 老司机发力移动娱乐竟成网红

文/张书乐 日前,网秦公布了截至2016年9月30日的第三季度未经审计财务业绩.移动增值服务以同比增长74.6%至5,490万美元的成绩成为网秦营收贡献的最大板块. 老司机网秦作为国内最老牌的移动互联网"巨鳄"之一,竟然依靠移动娱乐实现了全面转型,而且网秦首席执行官许泽民更表示:"我们对移动娱乐业务领域取得的持续进展感到满意,随着2016年进入最后一个季度,我们会继续专注于执行我们的战略." 真的简单就是一个战略而已?网秦怎么就突然成了"网红"呢

docker centos rpm离线安装1.8.2及pull的正确姿势

1.离线安装 本次只针对1.8.2版本,所需要的rpm包如下 docker-engine-1.8.2-1.el7.centos.x86_64.rpm(已上传51cto) libcgroup-0.41-8.el7.x86_64.rpm libcgroup-devel-0.41-8.el7.x86_64.rpm libcgroup-pam-0.41-8.el7.x86_64.rpm libcgroup-tools-0.41-8.el7.x86_64.rpm(libcgroup请参考开源镜像库) 简单