POJ 1703 Find them, Catch them【典型并查集:判断在不同的集合】
2013-04-08 19:04
531 查看
TimeLimit:1000MS | MemoryLimit:10000K | |
TotalSubmissions:23915 | Accepted:7167 |
ThepoliceofficeinTaduCitydecidestosayendstothechaos,aslaunchactionstorootuptheTWOgangsinthecity,GangDragonandGangSnake.However,thepolicefirstneedstoidentifywhichgangacriminalbelongsto.Thepresentquestionis,given
twocriminals;dotheybelongtoasameclan?Youmustgiveyourjudgmentbasedonincompleteinformation.(Sincethegangstersarealwaysactingsecretly.)
AssumeN(N<=10^5)criminalsarecurrentlyinTaduCity,numberedfrom1toN.Andofcourse,atleastoneofthembelongstoGangDragon,andthesameforGangSnake.YouwillbegivenM(M<=10^5)messagesinsequence,whichareinthefollowingtwokinds:
1.D[a]
where[a]and[b]arethenumbersoftwocriminals,andtheybelongtodifferentgangs.
2.A[a][b]
where[a]and[b]arethenumbersoftwocriminals.Thisrequiresyoutodecidewhetheraandbbelongtoasamegang.
Input
ThefirstlineoftheinputcontainsasingleintegerT(1<=T<=20),thenumberoftestcases.ThenTcasesfollow.EachtestcasebeginswithalinewithtwointegersNandM,followedbyMlineseachcontainingonemessageasdescribedabove.
Output
Foreachmessage"A[a][b]"ineachcase,yourprogramshouldgivethejudgmentbasedontheinformationgotbefore.Theanswersmightbeoneof"Inthesamegang.","Indifferentgangs."and"Notsureyet."
SampleInput
1 55 A12 D12 A12 D24 A14
SampleOutput
Notsureyet. Indifferentgangs. Inthesamegang.
Source
[b]题意
有T组测试数据。
给你N个人,编号从1到N,操作M次。
每次操作输入一个字符和两个数x,y
如果字符为A则判断x和y是否属于同一个帮派,并且输出结果。
如果字符为D则明确告诉你x和y是属于不同帮派的。
算法:经典并查集的应用。
PS:以前接触的并查集都是让我们判断是否属于同一个连通分量,但这道题却让你判断是否属于同一类。
开始小纠结了下,如果我昨天没有纠结清楚
那题的简单版本。
思路:除了像普通的并查集定义一个p[]记录父亲节点外,还定义一个r[]记录当前点与其所属的连通分量的根节点的关系。
r[]=0表示属于同一个帮派;r[]=1表示与其根节点属于不同的帮派。
开始时初始化自己是自己的父亲p[x]=x,自己与自己属于同一类r[x]=0.
一旦输入D断定x和y属于不同集合后,就连接x和y所在的树,同时更新r[]
一旦输入A
如果find(x)不等于find(y)说明还没有判断过x与y直接输出关系不确定即可
Notsureyet.
如果find(x)等于find(y),但是他们的r不等,说明属于不同帮派,输出Indifferentgangs.
如果他们的r相等,说明属于同一个帮派,则输出Inthesamegang
注意:1.find()函数寻找根节点的时候要不断的更新r
根据子节点与父亲节点的关系和父节点与爷爷节点的关系,推导子节点与爷爷节点的关系
如果a和b的关系是r1,b和c的关系是r2,
那么a和c的关系就是(r1+r2)%2.PS:因为只用两种情况所以对2取模。
如果实在不好理解,那么我们就枚举推理一下,共有2*2=4种情况:
(a,b)(b,c)(a,c)(r1+r2)%2
0 000a和b是同类,b和c是同类,所以a和c也是同类
0111a和b是同类,b和c是异类,所以a和c也是异类
1011a和b是异类,b和c是同类,所以a和c是异类
1100a和b是异类,b和c是异类,所以a和c是同类
2.Union()联合两棵树的时候也要更新两棵树的根的关系
定义:fx为x的根节点,fy为y的根节点
联合时,使得p[fx]=fy;同时也要寻找fx与fy的关系。关系为:(r[x]+r[y]+1)%2
如何证明?
fx与x的关系是r[x],
x与y的关系是1(因为确定是不同类,才联合的),
y与fy关系是r[y],模2是因为只有两种关系
所以又上面的一点所推出的定理可以证明fx与fy的关系是:(r[x]+r[y]+1)%2
D
Accepted
916KB
329ms
C++
1120B
2013-04-0818:29:33
*/
#include<cstdio>
constintmaxn=100000+10;
intp[maxn];//存父亲节点
intr[maxn];//存与根节点的关系,0代表同类,1代表不同类
intfind(intx)//找根节点
{
if(x==p[x])returnx;
intt=p[x];//记录父亲节点方便下面更新r[]
p[x]=find(p[x]);
r[x]=(r[x]+r[t])%2;//根据子节点与父亲节点的关系和父节点与爷爷节点的关系,推导子节点与爷爷节点的关系
returnp[x];//容易忘记
}
voidUnion(intx,inty)
{
intfx=find(x);//x所在集合的根节点
intfy=find(y);
p[fx]=fy;//合并
r[fx]=(r[x]+1+r[y])%2;//fx与x关系+x与y的关系+y与fy的关系=fx与fy的关系
}
voidset(intn)
{
for(intx=1;x<=n;x++)
{
p[x]=x;//自己是自己的父节点
r[x]=0;//自己和自己属于同一类
}
}
intmain()
{
intT;
intn,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%*c",&n,&m);
set(n);
charc;
intx,y;
while(m--)
{
scanf("%c%d%d%*c",&c,&x,&y);//注意输入
//printf("%c\n",c);
if(c=='A')
{
if(find(x)==find(y))//如果根节点相同,则表示能判断关系
{
if(r[x]!=r[y])printf("Indifferentgangs.\n");
elseprintf("Inthesamegang.\n");
}
elseprintf("Notsureyet.\n");
}
elseif(c=='D')
{
Union(x,y);
}
}
}
return0;
}
相关文章推荐
- POJ 1703 Find them, Catch them【典型并查集:判断在不同的集合】
- (POJ 1703) Find them, Catch them【典型并查集:判断在不同的集合】
- (用树结构支持并查集8.2.2)POJ 1703 Find them, Catch them(并查集的简单使用: 判断两个元素是否属于同一集合)
- POj 1703 Find them, Catch them(关系并查集)
- POJ 1703 Find them, Catch them 种类并查集
- POJ1703 Find them, Catch them 并查集
- POJ 1703 Find them, Catch them(关系并查集)
- POJ 1703 Find them, Catch them 并查集 (关系问题 判断是否在一个集合)
- 并查集 示例 : poj 1703 [Find them, Catch them - 帮派之争]
- poj 1703 Find them, Catch them(并查集)
- poj 1703 Find them, Catch them 并查集
- POJ 1703 Find them, Catch them【并查集】
- POJ 1703 Find them, Catch them 种类并查集
- poj 1703 Find them, Catch them 带权并查集
- poj1703 Find them, Catch them(带权并查集)
- poj 1703 Find them, Catch them(带权并查集)
- POJ 1703 Find them, Catch them(路径压缩并查集)
- POJ 1703 Find them, Catch them 并查集
- POJ 1703 Find them, Catch them(分类并查集)
- POJ 1703 Find them, Catch them 并查集 (关系问题 判断是否在一个集合)