博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ1703 Find them, Catch them(并查集)
阅读量:4981 次
发布时间:2019-06-12

本文共 7860 字,大约阅读时间需要 26 分钟。

题目链接:

塔都市的警察局决定以混乱为目标,作为启动行动,扎根城市中的两个帮派,Gang Dragon和Gang Snake。
但是,警方首先需要确定犯罪分子属于哪个团伙。目前的问题是,两名罪犯; 他们属于同一个氏族吗?
您必须根据不完整的信息做出判断。(因为歹徒总是暗中行动。)
假设N(N <= 10 ^ 5)罪犯目前在塔都市,编号从1到N.当然,他们中至少有一人属于Gang Dragon,
同样为Gang Snake。您将按顺序给出M(M <= 10 ^ 5)个消息,它们分为以下两种:
1。D [a] [b]
其中[a]和[b]是两个罪犯的数字,以及他们属于不同的帮派。
2. A [a] [b]
其中[a]和[b]是两个罪犯的数量。这需要您决定a和b是否属于同一个团伙。
输入
输入的第一行包含单个整数T(1 <= T <= 20),即测试用例的数量。然后是T案例。
每个测试用例以具有两个整数N和M的行开始,接着是M行,每行包含如上所述的一个消息。
产量
对于每种情况下的每条消息“A [a] [b]”,您的程序应根据之前获得的信息进行判断。
样本输入
1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4
样本输出
Not sure yet.
In different gangs.
In the same gang.
这个题目也是典型的并查集的题目,因为总共只有两个黑帮,所以可以用两个集合来求解。当让,用一个集合也可以。
只是要对relation进行细心设置(可以设置relatiin:0表示关系相同,1为关系不同)。在对一个元素执行Find()操作时,如果它与父亲结点realtion相同,父亲结点与根结点relation相同,那么该元素与根结点关系也相同。否则是不同的。
1 int DisJoinSet ::Find(int x) 2 { 3     int temp = tree[x].parent;//temp x的父亲结点 4     if(x != tree[x].parent) 5     { 6         tree[x].parent = Find(tree[x].parent);//递归在双亲中找x 7     // tree[temp].relation必为temp结点(x的父节点)与根节点的关系,tree[x].relation最初为x与temp的关系, 8     // tree[x].relation == tree[temp].relation意味着tree[x].relation和tree[temp].relation同为1,或者同为0 9     // 如果tree[x].relation和tree[temp].relation同为1,意味着根节点与temp不同类,temp与x不同类,总共只有2个集合,x与根节点必定同类。10     // 如果tree[x].relation和tree[temp].relation同为0,意味着根节点与temp同类,temp与x同类,x与根节点也必定同类。11         if(tree[x].relation == tree[temp].relation)12         {13             tree[x].relation = 0;14         }15     // tree[x].relation != tree[temp].relation意味着tree[x].relation和tree[temp].relation一个为1,一个为0,16     // 如果tree[temp].relation为false,tree[temp].relation为1,意味着根节点和temp同类,temp与x不同类,那么x与根节点必然不同类17     // 如果tree[temp].relation为true,tree[x].relation为0,意味着根节点和temp不同类,temp与x同类,那么x与根节点必然不同类18         else19         {20             tree[x].relation = 1;21         }    22         return tree[x].parent;// 返回根节点下标23     }24     else25     {26         return x;27     }28 }
View Code
在进行合并操作时,因为合并的x和y是属于不同集合的,所以和上面一样的推理。
1 void DisJoinSet ::Union(int x,int y) 2 { 3     int rootx = Find(x); 4     int rooty = Find(y); 5     if(rootx == rooty) 6     { 7         return ; 8     } 9     if(tree[rootx].rank > tree[rooty].rank)10     {11         tree[rooty].parent = rootx;12         // 此时rooty与其根结点rootx的关系如何确定?因为Find方法也在进行路径压缩,x的父节点是rootx,y的父节点的rooty13         // 如果tree[x].relation和tree[y].relation均为1,说明x和rootx不同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx不同类;14         // 如果tree[x].relation和tree[y].relation均为0,说明x和rootx同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx不同类15         if(tree[x].relation == tree[y].relation)16         {17             tree[rooty].relation = 1;18         }19         // 如果tree[x].relation为1,tree[y].relation为0,说明x和rootx不同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx必同类;20         // 如果tree[x].relation为0,tree[y].relation为1,说明x和rootx同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx必同类;21         else22         {23             tree[rooty].relation = 0;24         }25     }26     else27     {28         tree[rootx].parent = rooty;29         if(tree[rootx].rank == tree[rooty].rank)30         {31             tree[rooty].rank ++;32         }33         // 此时rooty与其根结点rootx的关系如何确定?因为Find方法也在进行路径压缩,x的父节点是rootx,y的父节点的rooty34         // 如果relation[x]和relation[y]均为true,说明x和rootx不同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx不同类;35         // 如果relation[x]和relation[y]均为false,说明x和rootx同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx不同类36         if(tree[x].relation == tree[y].relation)37         {38             tree[rootx].relation = 1;39         }40         // 如果tree[x].relation为1,tree[y].relation为0,说明x和rootx不同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx必同类;41         // 如果tree[x].relation为0,tree[y].relation为1,说明x和rootx同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx必同类;42         else43         {44             tree[rootx].relation = 0;45         }46     }47 }
View Code

完整代码:

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 using namespace std; 15 16 struct node 17 { 18 int no; 19 int rank; 20 int parent; 21 int relation; 22 }; 23 24 class DisJoinSet 25 { 26 protected: 27 int n; 28 node *tree; 29 public : 30 DisJoinSet(int n); 31 ~DisJoinSet(); 32 void Init(); 33 void Union(int x,int y); 34 int Find(int x); 35 bool itsSame(int x,int y); 36 }; 37 38 DisJoinSet ::DisJoinSet(int n) 39 { 40 this->n = n; 41 tree = new node[n+1]; 42 Init(); 43 } 44 45 DisJoinSet ::~DisJoinSet() 46 { 47 delete []tree; 48 } 49 50 void DisJoinSet::Init() 51 { 52 for(int i = 1; i <= n; i ++) 53 { 54 tree[i].no = i; 55 tree[i].rank = 0; 56 tree[i].parent = i; 57 tree[i].relation = 0; 58 } 59 } 60 61 int DisJoinSet ::Find(int x) 62 { 63 int temp = tree[x].parent;//temp x的父亲结点 64 if(x != tree[x].parent) 65 { 66 tree[x].parent = Find(tree[x].parent);//递归在双亲中找x 67 // tree[temp].relation必为temp结点(x的父节点)与根节点的关系,tree[x].relation最初为x与temp的关系, 68 // tree[x].relation == tree[temp].relation意味着tree[x].relation和tree[temp].relation同为1,或者同为0 69 // 如果tree[x].relation和tree[temp].relation同为1,意味着根节点与temp不同类,temp与x不同类,总共只有2个集合,x与根节点必定同类。 70 // 如果tree[x].relation和tree[temp].relation同为0,意味着根节点与temp同类,temp与x同类,x与根节点也必定同类。 71 if(tree[x].relation == tree[temp].relation) 72 { 73 tree[x].relation = 0; 74 } 75 // tree[x].relation != tree[temp].relation意味着tree[x].relation和tree[temp].relation一个为1,一个为0, 76 // 如果tree[temp].relation为false,tree[temp].relation为1,意味着根节点和temp同类,temp与x不同类,那么x与根节点必然不同类 77 // 如果tree[temp].relation为true,tree[x].relation为0,意味着根节点和temp不同类,temp与x同类,那么x与根节点必然不同类 78 else 79 { 80 tree[x].relation = 1; 81 } 82 return tree[x].parent;// 返回根节点下标 83 } 84 else 85 { 86 return x; 87 } 88 } 89 90 void DisJoinSet ::Union(int x,int y) 91 { 92 int rootx = Find(x); 93 int rooty = Find(y); 94 if(rootx == rooty) 95 { 96 return ; 97 } 98 if(tree[rootx].rank > tree[rooty].rank) 99 {100 tree[rooty].parent = rootx;101 // 此时rooty与其根结点rootx的关系如何确定?因为Find方法也在进行路径压缩,x的父节点是rootx,y的父节点的rooty102 // 如果tree[x].relation和tree[y].relation均为1,说明x和rootx不同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx不同类;103 // 如果tree[x].relation和tree[y].relation均为0,说明x和rootx同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx不同类104 if(tree[x].relation == tree[y].relation)105 {106 tree[rooty].relation = 1;107 }108 // 如果tree[x].relation为1,tree[y].relation为0,说明x和rootx不同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx必同类;109 // 如果tree[x].relation为0,tree[y].relation为1,说明x和rootx同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx必同类;110 else111 {112 tree[rooty].relation = 0;113 }114 }115 else116 {117 tree[rootx].parent = rooty;118 if(tree[rootx].rank == tree[rooty].rank)119 {120 tree[rooty].rank ++;121 }122 // 此时rooty与其根结点rootx的关系如何确定?因为Find方法也在进行路径压缩,x的父节点是rootx,y的父节点的rooty123 // 如果relation[x]和relation[y]均为true,说明x和rootx不同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx不同类;124 // 如果relation[x]和relation[y]均为false,说明x和rootx同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx不同类125 if(tree[x].relation == tree[y].relation)126 {127 tree[rootx].relation = 1;128 }129 // 如果tree[x].relation为1,tree[y].relation为0,说明x和rootx不同类,y和rooty同类,而已知x和y不同类,因此rooty和rootx必同类;130 // 如果tree[x].relation为0,tree[y].relation为1,说明x和rootx同类,y和rooty不同类,而已知x和y不同类,因此rooty和rootx必同类;131 else132 {133 tree[rootx].relation = 0;134 }135 }136 }137 138 139 bool DisJoinSet::itsSame(int x,int y)140 {141 return (tree[x].relation == tree[y].relation);142 }143 144 145 int main()146 {147 int T;148 while(scanf("%d",&T) !=EOF )// 没有EOF 会 OLE149 {150 if(T == 0)break;151 for(int i = 0; i < T; i++)152 {153 int N;154 int M;155 scanf("%d%d",&N,&M);156 DisJoinSet dis(N);157 char s1[2];158 int s2,s3;159 for(int i= 0; i < M ;i ++)160 {161 scanf("%s%d%d",s1,&s2,&s3);162 int pa = dis.Find(s2);163 int pb = dis.Find(s3);164 if(s1[0] == 'A')165 {166 if(pa != pb)167 {168 cout<<"Not sure yet."<
View Code

 

转载于:https://www.cnblogs.com/ygsworld/p/11141050.html

你可能感兴趣的文章
pageUtil分页工具
查看>>
HDU1175 连连看(DFS)
查看>>
摄影中的曝光补偿、白加黑减
查看>>
数据结构实验2-迷宫
查看>>
select 的字段为空,给他显示默认值
查看>>
[LeetCode] Best Time to Buy and Sell Stock
查看>>
结构化方法与面向对象方法之比较
查看>>
Link cut tree学习笔记
查看>>
vue路由跳转时更改页面title
查看>>
.net转的时间戳用java去解析的代码
查看>>
使用Groovy+Spock构建可配置的订单搜索接口测试用例集
查看>>
python基础——使用dict和set
查看>>
# Day04-Android
查看>>
读写方式 r , r+ , w , w+ , a , a+
查看>>
SQL SERVER中求上月、本月和下月的第一天和最后一天
查看>>
redis配置文件
查看>>
案例15-基本的表单校验使用validate
查看>>
推荐-Everything搜索工具
查看>>
关于单片机编程里面调用sprintf死机的解决方法及原因分析
查看>>
javascript与python的比较
查看>>