Find them, Catch them
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 4Sample Output
Not sure yet. In different gangs. In the same gang.
参考网址:::::https://blog.csdn.net/jaihk662/article/details/52013762 题解参考
参考网址:::https://blog.csdn.net/qq_33583069/article/details/51225372 注释参考
::::::https://blog.csdn.net/yinghui_yht/article/details/53363012 注释参考
参考网址:::https://blog.csdn.net/qq_18738333/article/details/48396497 代码参考
题意:某同一个城市有两个团伙,给出t代表有多少组数据,n代表人数,m代表关系的数目,如果输入的是A的话,就是让我们来判断这两个人是否属于同一个团伙,如果输入的是D 的话,旧表示这两个人是不同的团伙。
思路:用到算法是种类并查集,用fa数组来存放节点与根节点,用gang数组来存放关系。
用0代表与gang[i]是同一个同伙的,1代表i与gang[i]不是同一个同伙的
重点1:在find1()函数中,我们用到
int temp=fa[t];
fa[t]=find1(temp);
gang[t]=(gang[t]+gang[temp])%2;
这一语句,其语义是,如果当前节点t与新节点或者新节点与旧节点的关系都是1或者0,那么当前节点t与新节点的关系就好判断了,要么是同伙,要么不是同伙。
重点2 :
void union_set(int a,int b)
{
int roota=find1(a);
int rootb=find1(b);
if(roota!=rootb)
{
fa[rootb]=roota;
gang[rootb]=(gang[a]+1-gang[b])%2;
}
}
用来查找a和b的祖先节点,如果其祖先节点不同的话,那么其关系就不确定,所以就要将两者的祖先链接起来,rootb的祖先节点是roota,再下面一条语句是用来判断a和b是什么样的关系
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
#define maxn 100100
int fa[maxn+1];
int gang[maxn+1];
int n,k;
void inist()
{
for(int i=0;i<=n;i++)
{
fa[i]=i;
gang[i]=0;
}
}
int find1(int t)
{
if(fa[t]==t)
return fa[t];
int temp=fa[t];
fa[t]=find1(temp);
gang[t]=(gang[t]+gang[temp])%2;
return fa[t];
}
void union_set(int a,int b)
{
int roota=find1(a);
int rootb=find1(b);
if(roota!=rootb)
{
fa[rootb]=roota;
gang[rootb]=(gang[a]+1-gang[b])%2;
}
}
int solve(int a,int b)
{
int roota=find1(a);
int rootb=find1(b);
if(roota!=rootb)
{
return 1;
}
else
{
if(gang[a]!=gang[b])
{
return 2;
}
else
{
return 3;
}
}
}
int main()
{
int t;
char op;
int a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
inist();
for(int i=0;i<k;i++)
{
getchar();
scanf("%c%d%d",&op,&a,&b);
if(op=='D')
{
union_set(a,b);
}
else
{
int res=solve(a,b);
if(res==1)
{
printf("Not sure yet.\n");
}else if(res==2)
{
printf("In different gangs.\n");
}else
{
printf("In the same gang.\n");
}
}
}
}
}
对于确定a和b的关系数组的做法和find1()函数修改关系的做
法,不是很理解,目前还没有彻底掌握,很迷茫的感觉,可能有
许多错误的地方,欢迎大家评论,谢谢~~~
注:详细注释
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int MAXN = 100100;
int fa[MAXN];
int gang[MAXN];
int n, k;
void init()
{
for (int i = 0; i <= n; i++)
{
fa[i] = i;
gang[i] = 0;//代表团伙关系,0代表i与gang[i]是同一个团伙的,1代表i与gang[i]不是同一个团伙的
}
}
int find1(int t)
{
//在find中更新gang的关系,当前节点t的父亲的父亲是根节点,我们可以通过当前节点t和它付钱的关系
//来判断当前节点t与根节点(其父亲的父亲的)关系
if (fa[t] == t)
return fa[t];
int temp = fa[t];
fa[t] = find1(temp);//用来找祖先节点
gang[t] = (gang[t] + gang[temp]) % 2;//代表当前节点t与其父亲节点temp的关系
//如果t与旧祖先的关系和旧祖先与新祖先的关系都为1或者0,那么t与新祖先的关系要么是同一个团伙,要么是不同的团伙。
cout<<"gang["<<t<<"]= "<<gang[t]<<endl;
return fa[t];
}
void union_set(int a, int b)
{
int roota = find1(a);
int rootb = find1(b);
if (roota != rootb)//根不相同,关系还不确定
{
fa[rootb] = roota;//更新根节点b中的值,将根节点a与根节点b相连接
//其中roota是rootb的父亲
gang[rootb] = (gang[a] + 1 - gang[b]) % 2;
//确认a和b的关系
cout<<"gang["<<rootb<<"]= "<<gang[rootb]<<endl;
}
}
int solve(int a, int b)
{
int roota = find1(a);
int rootb = find1(b);
if (roota != rootb)
{
return 1;
}
else
{
if (gang[a] != gang[b])
return 2;
else
return 3;
}
}
int main()
{
int casen;
scanf("%d", &casen);
while (casen--)
{
scanf("%d%d", &n, &k);
init();
char op;
int a, b;
for (int i = 0; i < k; i++)
{
cin >> op;
scanf("%d%d", &a, &b);
if (op == 'D')
{
union_set(a, b);
}
else
{
int ret = solve(a, b);
if (ret == 1)
printf("Not sure yet.\n");
else if (ret == 2)
printf("In different gangs.\n");
else
printf("In the same gang.\n");
}
}
}
}