Find them, Catch them(种类并查集)POJ - 1703
The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.)
Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:
1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.
2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.
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.
题意:在一个城市中有两个帮派,龙邦和蛇帮,警察决定铲除它们。
给你N,M两个值,表示有N个罪犯,以1-N作为编号,再有M行,以D开头表示a,b是不同帮派的,以A开头,表示询问a,b两个人的关系。
如果同一帮派,In the same gang.
如果不同帮派,In different gangs.
如果不知道关系,Not sure yet.
思路:很显然是用种类并查集,普通并查集是以朋友的朋友还是朋友的思路串在一起。而种类并查集是以敌人的敌人是朋友联系在一起。
我们开一个两倍的并查集。例如,假如我们要维护4个元素的并查集,我们改为开8个单位的空间:
如果1和2是不同帮派的,我们可以把(1+N,2),(1,2+N)连在一起。
如果2和4又是不同帮派的,我们再把(2+N,4),(2,4+N)连在一起。
这图又可以看出什么呢?从图可知(2,5)(2,8)是连在一起的,表示2和5是不同帮派的,2和8也是不同帮派的,则5和8是同一帮派的,1(5-N)和4(8-N)是同一帮派的。
基于以上思想,我们可以写出下面的代码。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstring> #include<stdio.h> #include<algorithm> #include<map> #include<queue> #include<set> #include <sstream> #include<vector> #include<cmath> #include<stack> #include<time.h> #include<ctime> using namespace std; #define inf 1<<30 #define eps 1e-7 #define LD long double #define LL long long #define maxn 1000000005 int pre[200009] = {}; int rootsearch(int root) { int son; son = root; while (root != pre[root])//这个数不是领导,继续往下找 { root = pre[root]; } while (son != root)//路径压缩,把找到的下级数全部指向最高领导 { int temp = pre[son]; pre[son] = root; son = temp; } return root;//返回最高领导 } int main() { int T; scanf("%d", &T); while (T--) { int N, M, a, b; char ch; scanf("%d%d", &N, &M); getchar(); for (int i = 1; i <= 2 * N; i++)//初始化一个两倍的数组 { pre[i] = i; } while(M--) { scanf("%c %d %d", &ch, &a, &b);//用cin会超时,别问我怎么知道的。。。 getchar(); if (ch == 'D') { pre[rootsearch(a + N)] = rootsearch(b);//把a+N和b联系在一起 pre[rootsearch(b + N)] = rootsearch(a);//把b+N和a联系在一起 } else { if (rootsearch(a) == rootsearch(b)||rootsearch(a+N)==rootsearch(b+N))//如果a,b或a+N,b+N的根节点一致 { printf("In the same gang.\n"); } else if (rootsearch(a) == rootsearch(b + N) || rootsearch(a + N) == rootsearch(b))//如果a,b+N或a+N,b的根节点一致 { printf("In different gangs.\n"); } else//两个人没有任何关系 { printf("Not sure yet.\n"); } } } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统