1. 程式人生 > >A Bug's Life(加權並查集)

A Bug's Life(加權並查集)

滴答滴答---題目連結 

A Bug's Life(加權並查集)

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!



題目意思:t組資料,n個蟲子,m組相互喜愛的關係,蟲子分為雌雄兩種,每個蟲子只有一個性別,問是否存在同性戀的蟲子。

解題思路:一開始我的思路是希望通過將蟲子劃分為雌雄兩個集合,看看這兩個集合中是否出現了環,出現了環則說明存在著同性戀。我看了看網上的題 解,給出了加權並查集的概念,這裡我就試著使用這個思想來解題。

加權並查集: 有的時候,不僅需要像普通並查集一樣記錄一些元素之間有無關係,還需要記錄它們之間有怎樣的關係,這時候就需要引入加權並查集。 通常情況下,用一個數組r來記錄這些關係,r[i]表示元素i與父結點的關係。至於是什麼關係,還要根據具體要求來看。 在find(x)函式中進行路徑壓縮的同時,許多結點的父結點會改變,這時就需要根據實際情況調整權值以保證其正確性。 在union(x,y)函式中,(不妨設將y集合併入x集合)由於y的父結點的改變,需要調整y對應的權值,但不需要調整y的子結點對應的權值,因為子結點 權值會在find(子結點)時得到調整。

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=100001;
int pre[maxn];
int r[maxn];//r=0代表與根節點同性
int fin(int x)
{

    int t;
    if(pre[x]==x)
        return x;
    t=pre[x];
    pre[x]=fin(pre[x]);
    r[x]=(r[x]+r[t]+1)%2;
    return pre[x];
}
void uni(int a,int b)
{
    int x,y;
    x=fin(a);
    y=fin(b);
    pre[x]=y;
    r[x]=(r[b]-r[a])%2;

}
int main()
{
    int t;
    scanf("%d",&t);
    int k=0;
    while(t--)
    {
        int flas=0;
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            r[i]=1;
            pre[i]=i;
        }
        for(int i=1; i<=m; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(fin(a)==fin(b))
            {
                if(r[a]==r[b])
                {
                    flas=1;
                }

            }
            else
            {
                uni(a,b);
            }
        }
        k++;
        if(flas)
        {
            printf("Scenario #%d:\nSuspicious bugs found!\n\n",k);
        }
        else
        {
            printf("Scenario #%d:\nNo suspicious bugs found!\n\n",k);
        }
    }
    return 0;
}