您的位置:首页 > 其它

POJ 1703 1182 2492 并查集 偏移

2013-10-10 23:01 393 查看
up[i]相对根节点偏移量(初始化0)

f[i]根节点(初始化i)

* get(int x)中维护 偏移量

int get(int x){
if(f[x]!=x){
int t=f[x];
f[x]=get(f[x]);
up[x]=(up[x]+up[t])%mod;
}
return f[x];
}


*bing(int st,int ed)中维护偏移量 x为相对关系,相同为0,不同为1

void bing(int st,int ed){
int f1=get(st),f2=get(ed);
if(f1!=f2){
f[f2]=f1;
up[f2]= (up[st] +up[ed]+x) % mod;
}
}


题意

1703

N个人,M条指令

M条指令,每条指令有2种情况

A x y 问 x 与 y 的关系

D x y 表示确定 x 和 y 属于不同的集团

对于A x y 的询问,

如果x与y属于同一集团输出In the same gang.

如果x与y属于不同集团输出In different gangs.

如果不能确定输出Not sure yet.

2492

N个虫子,M条关系

M种关系,每种关系 x y

表示x与y 可以交配..

问:对于输入的信息中 出现的同性恋的个数

同性恋出现的情况举例

分别有关系 a b ,b c ,c a,a和c 都能与b 交配,假如b为雌性,a,c为雄性,但是有关系a c,a 与c也能交配则出现同性恋。

上述两题基本属于同样的问题,只是问的问题稍有不同..

对于输入的每条信息首先判断两个节点的根节点是否相同,

如果不同则进行合并同时维护2个数组f[](根节点编号)up[]与根节点的距离(如果属于了不同集团或者是不同性别距离为1).

如果相同则进行判断 看up[x]+up[y]的值的奇偶性,()奇数则不同集团/不同性别,偶数相同集团/相同性别

对于询问中的x y,如果x 和y 属于不同集合则不能确定.

1182

/article/8867624.html

N个动物M个关系

M种关系 D x y

若D=1,则表示X和Y是同类。

若D=2,则表示X吃Y。

这个题中的关系与之前的略有不同,前面的题都是一个属性集团/性别只有2种,是可以根据相对关系唯一确定的。

这个的相对关系有3种,对于A>B>C>A这样一个循环的食物链可能有A B捕食关系 也可能有A C被捕食关系.

这将导致不能单纯的以2个节点相对于根节点的距离和的奇偶性来判断关系

d表示的是相对关系0 表示相同,1表示捕食,2表示被捕食

假如 a相对b 关系为1 即a吃b,然后有b相对c 关系为1 ,即b吃c 则a相对c 的关系正好是 up[a]+up[b]=2;

不过有一个神奇的公式 用于bing 操作中,get操作中和之前一样即可~

up[f2]=(-up[ed]+(d-1)+up[st]+mod)%mod;


void bing(int d,int st,int ed){
int f1=get(st),f2=get(ed);
if(f1!=f2){
f[f2]=f1;
up[f2]=(-up[ed]+(d-1)+up[st]+3))%3;
}
}


#include<stdio.h>
#include<string.h>
int up[50005],f[50005];
int n,tot;
int get(int x){
if(x== f[x]) return x;
if(f[x]!=x){
int t=f[x];
f[x]=get(f[x]);
up[x]=(up[x]+up[t]+3)%3;
}
return f[x];
}
void bing(int d,int st,int ed){
if((d==2&&st==ed)||st>n||ed>n){
tot++;return ;
}
int f1=get(st),f2=get(ed);
if(f1==f2){
if(d==2){
if((up[ed]-up[st]+3)%3!=1)tot++;
}else if((up[ed]-up[st]+3)%3!=0)tot++;
}else {
f[f2]=f1;
up[f2]=((3-up[ed]+(d-1)+up[st]))%3;
}
}
int main(){
int m,d,st,ed;
scanf("%d %d",&n,&m);
for(int i=0;i<=n;i++){
f[i]=i,up[i]=0;
}
tot=0;
while(m--){
scanf("%d %d %d",&d,&st,&ed);
if(st>n||ed>n){
tot++;continue;
}
if(d==2&&st==ed){
tot++;continue;
}
bing(d,st,ed);
}
printf("%d\n",tot);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: