您的位置:首页 > 其它

POJ 1703 Find them, Catch them(并查集,向量偏移)

2012-08-30 23:40 525 查看
http://poj.org/problem?id=1703

题目大意:有一些黑帮的人分为两派,然后给出一些语句,D代表两个人在不同的帮派里,A代表输出两人的关系(不确定,在一个帮派里或不在一个帮派里)。做之前就知道这题是并查集的题目但是还是没什么思路,看题解也没看明白,后来看一位大牛讲解向量偏移的博客才明白了一点http://hi.baidu.com/tomspirit/item/d1f2a19b2aaf36d27a7f0158,向量偏移的思想这里也不赘述了,就是把关系的转移用类似向量的方式计算,维护一个off数组代表第x个元素与根节点关系,0表示属于同一个帮派,1表示不在一个帮派,在添加一组新的关系时,除了并查集的常规更新,还要更新一下off的值,详见代码。

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
int pa[100005];
int off[100005];
char str[2];
int find(int k)
{
if(pa[k]==k)
return k;
int temp=pa[k];     //记录k原来的父节点
pa[k]=find(temp);   //并查集的常规更新
off[k]=(off[k]-off[temp]+2)%2;   //网上很多代码都不是这么写的,不过我觉得这样写更容易理解,而且还要快一些
//off[k]表示k节点原来的根节点到k的偏移量,off[temp]表示根节点到k原来的父节点的偏移量,我们要的off的值应该是k与其父节点之间的关系根据向量相减的原理,即得上式
return pa[k];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
pa[i]=i;
off[i]=0;
}
for(int i=0;i<m;i++)
{
int x,y;
scanf("%s%d%d",str,&x,&y);
int pax=find(x);
int pay=find(y);
if(str[0]=='D')
{
if(pax!=pay)
{
pa[pay]=pax;
off[pay]=(off[x]+1-off[y])%2;     //off表示pax到pay的偏移量,即为pax到x的偏移量+x到y+y到pay
}
}
else if(str[0]=='A')
{
if(pax==pay)
{
if(off[x]==off[y])
{
puts("In the same gang.");
}
else puts("In different gangs.");
}
else puts("Not sure yet.");
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: