並查集//POJ1182

第一行:咕咕咕。

第二行:我原以爲並查集很簡單的。原以爲。因此我現在一看到說並查集“簡單有趣”的博客就心情複雜(不排除對人家來說真的簡單有趣)。(本博客下次更新會附送簡單並查集緩解心情)

第三行:誰能想到一道並查集我花了兩個晚上呢。

第四行:這道題需要多多複習,我現在也不是特別明白。

第五行:還是小白書友好一些。

第六行:真正的勇士,敢於wa題二十次。

並查集:快速判斷兩個或多個元素的關係,快速合併兩個集合
基礎的合併or查找父節點我就不寫了(包括遞歸查找和while循環查找)

本題POJ1182:兩種思路:一種類似於向量;另一種分作三個區間0 ~ n表示同類,n+1 ~ 2n表示被吃,2n+1 ~ 3n表示吃別的(白書給出的思想
所附代碼爲第一種思路(用相對關係來表示其關係)
會再抽個合適的時間去寫一下白書的代碼的(其實是學一下白書的代碼,因爲這個思路在關係合併那裏還是不太明白
留個坑

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 500005

using namespace std;
//當前寫法爲按向量來寫
int f[maxn];
int r[maxn];//一個表示父節點一個表示關係(同類
void init()
{
    for(int i = 0; i < maxn; ++i)
    {
        f[i]=i;
        r[i]=0;
    }
}

int tofind(int x)
{
    if(x==f[x])
        return x;
    int a=f[x];
    int b=x;
    x=tofind(f[x]);
    f[b]=x;
    r[b]=(r[a]+r[b])%3;
    return x;
}

void tojoin(int x,int y,int op)
{
    int a=tofind(y);
    f[a]=tofind(x);
    r[a]=(3-r[y]+op-1+r[x])%3;
}
int main()
{
    init();
    int n,k;
    int ans=0;
    scanf("%d%d",&n,&k);
    for(int i = 0; i < k; ++i)
    {
        int x,y,op;
        scanf("%d%d%d",&op,&x,&y);
        if(x>n||y>n||(op==2&&x==y))
            ans++;
        else
        {
            int r1=tofind(x);
            int r2=tofind(y);//未合併過即沒有關係
            if(r1==r2)
            {
                if(op==1)
                {
                    if(r[x]!=r[y])
                        ans++;
                }
                else
                {
                    if((3-r[x]+r[y])%3!=1)
                        ans++;
                }
            }
            else
            {
                tojoin(x,y,op);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

附幾個很不錯的題解(有空再看看:
添加鏈接描述
添加鏈接描述
添加鏈接描述
再附幾個簡單的並查集緩緩心情SDNU1351

發佈了41 篇原創文章 · 獲贊 10 · 訪問量 3499
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章