1. 程式人生 > >使用並查集來維護不同的類關系

使用並查集來維護不同的類關系

祖先 特殊 當前 () str -- 節點 數據結構 const

我們理解並查集這個數據結構的時候不要過於死板,我們要知道

並查集是用來維護關系的,而不是單純一味去歸並,歸並,歸並

下面給出一個問題嘗試用並查集來解決:一共有兩個類,然後告訴你若幹組數據,每一組數據的兩個元素不是一類的,然後在線判斷兩個元素是否是同一類

這個時候如果你只會歸並就行不通的,還需要一些特殊的處理

我們需要在並查集的那個數組的基礎之上,需要另一個數組來記錄這種特殊的現象

int set[maxn],a[maxn];
//a表示這個節點和父節點的關系,0表示相同1表示不同 

接下來我們的路徑壓縮加找祖宗函數也需要相應的調整,要不斷更新a的值才行

int find(int x)
{
    
if (x==set[x]) return x; //x的父節點是祖先節點的情況,不需要改變a的值 int t=find(set[x]); a[x]=(a[set[x]]+a[x])%2; //判斷歸並之後x和祖先的團夥關系 return set[x]=t; }

歸並的時候還是很簡單的,但是也要同時去更新a的值

void Union(int x, int y)
{
    int fx=find(x);
    int fy=find(y);
    set[fx]=fy;
    //根據x和y不同確定x和x的祖先節點的同夥關系 
    if (a[y]==0
) a[fx]=1-a[x]; else a[fx]=a[x]; }

我們在判斷的時候,已知的情況都已經歸並到一棵樹裏面,並且有a數組記錄已知情況下所有元素的關系,直接判斷即可

fx=find(x);
                fy=find(y);
                if (fx!=fy)
                    printf("Not sure yet.\n");
                else if(a[x]==a[y])
                    printf("In the same gang.\n
"); else printf("In different gangs.\n");

接下來我們給出完整的實現,這道題的大意是這樣的,有兩個犯罪團夥,然後告訴你若幹個關系,關系是兩個犯人不是一個團夥的,然後在線判斷給定的兩個犯人之間的關系

 1 //一共有兩類,給定某兩個元素之間的不同類關系
 2 //判斷當前給定情況下某兩個元素是否同類 
 3 #include<iostream>
 4 #include <cstdio>
 5 #include <cstring>
 6 using namespace std;
 7 const int maxn=100005;
 8 int t,n,m;
 9 int fx,fy,x,y;
10 char c;
11 int set[maxn],a[maxn];
12 //a表示這個節點和父節點的關系,0表示相同1表示不同 
13 int find(int x)
14 {
15     if (x==set[x]) return x;
16     //x的父節點是祖先節點的情況,不需要改變a的值 
17     int t=find(set[x]);
18     a[x]=(a[set[x]]+a[x])%2;
19     //判斷歸並之後x和祖先的團夥關系 
20     return set[x]=t;
21 }
22 void Union(int x, int y)
23 {
24     int fx=find(x);
25     int fy=find(y);
26     set[fx]=fy;
27     //根據x和y不同確定x和x的祖先節點的同夥關系 
28     if (a[y]==0)
29         a[fx]=1-a[x];
30     else
31         a[fx]=a[x];
32 }
33 int main()
34 {
35 
36     cin>>t;
37     while (t--)
38     {
39         cin>>n>>m;
40         for (int i=1; i<=n; i++)
41         {
42             set[i] = i;
43             a[i] = 0;
44         }
45         while(m--)
46         {
47             cin>>c>>x>>y;
48             if (c==A)
49             {
50                 fx=find(x);
51                 fy=find(y);
52                 if (fx!=fy)
53                     printf("Not sure yet.\n");
54                 else if(a[x]==a[y])
55                     printf("In the same gang.\n");
56                 else
57                     printf("In different gangs.\n");
58             }
59             else
60                 Union(x, y);
61         }
62     }
63     return 0;
64 }

使用並查集來維護不同的類關系