种类并查集

A Bug's Life

Time Limit : 20000/10000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 23   Accepted Submission(s) : 8
Problem Description
Background 
Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their interactions were easy to identify, because numbers were printed on their backs. 
Problem 
Given a list of bug interactions, decide whether the experiment supports his assumption of two genders with no homosexual bugs or if it contains some bug interactions that falsify it.
 

Input
The first line of the input contains the number of scenarios. Each scenario starts with one line giving the number of bugs (at least one, and up to 2000) and the number of interactions (up to 1000000) separated by a single space. In the following lines, each interaction is given in the form of two distinct bug numbers separated by a single space. Bugs are numbered consecutively starting from one.
 

Output
The output for every scenario is a line containing "Scenario #i:", where i is the number of the scenario starting at 1, followed by one line saying either "No suspicious bugs found!" if the experiment is consistent with his assumption about the bugs' sexual behavior, or "Suspicious bugs found!" if Professor Hopper's assumption is definitely wrong.
 

Sample Input
  
  
2 3 3 1 2 2 3 1 3 4 2 1 2 3 4
 

Sample Output
  
  
Scenario #1: Suspicious bugs found! Scenario #2: No suspicious bugs found!

 

种类并查集,以及权并查集需要关注的是向量偏移的操作。

假设出现的情况为已知x与fa的关系,以及y与fa的关系。

要去定x与y的关系根据向量的规则x->y=x->fa+fa->y;  即x->y = -(fa->x)+fa->y;

如果出现多个关系需要压缩的时候例如:


在y没有加入的时候,找x与ffa的关系的时候,已知x与fa的关系,以及fa与ffa的关系,即x->ffa = x->fa+fa->ffa;

在y加入的时候,要确定y与ffa的关系,现在已经知道x与ffa 的关系,所以y->ffa = y->x+x->ffa;

本题中为种类并查集,在压缩完路径之后,需要确定y与ffa之间的关系,我们用0表示y与ffa为同性,用1表示y与ffa为异性。所以在最后得到y->ffa的值之后需要对2求余。

void InitSet(int n)<span style="white-space:pre">			</span>//初始化数组 father[]存储父亲节点,rank存储y到ffa之间的向量偏移。
{
    for(int i = 1; i <= n ; i++)
    {
        father[i] = i;
        rank[i] = 0;
    }
}

int FindSet(int a)<span style="white-space:pre">	</span>//路径压缩,改变向量偏移的操作。
{
    if(father[a] != a)
    {
        int t = father[a];<span style="white-space:pre">		</span>//存储父亲节点,在回溯的时候(路径压缩的事后)求当前节点一父节点的向量偏移
        father[a] = FindSet(father[a]);
        rank[a] = (rank[a] +rank[t])%2;<span style="white-space:pre">	</span>//mod2,以确定与父亲节点的关系。
    }
    return father[a];
}

void UnionSet(int a,int b,int d)<span style="white-space:pre">		</span>//加入集合当中。
{
    int x = FindSet(a);
    int y = FindSet(b);
    father[x] = y;
    rank[x]=(rank[b]-rank[a]+3+d)%2;<span style="white-space:pre">		</span>//如下图
}


找fa->fb的关系的话,已知a->fa,a->b,b->fb的关系,那么fa->fb=fa->a+a->b+b->fb;   即fa->fb = -(a->fa)+a->b+b->fb;


  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ink__Bamboo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值