1. 程式人生 > 實用技巧 >SP3377《A Bug's Life》

SP3377《A Bug's Life》

原更新時間:2018-10-20 09:51:14

誰閒的沒事研究同性戀。。。

題目地址

本文同步釋出於:Handwer's 洛谷部落格

題目大意

就是一個奇怪的ke學家,他專門研究蟲子是否存在同性戀。。。

他為每一隻蟲子都標上了序號。

通過這個奇怪的ke學家的研究,找出了在這些蟲子中的所有關係的蟲子,題目詢問在這麼多有關係的蟲子中是否存在“同性戀”。

輸入格式 & 樣例

第一行, 輸入一個數,表示有t組資料
對於每組資料,第一行輸入n,m,表示有n只蟲子,有m個關係
接下來行每行兩個數x,y,表示x,y有關係

2
3 3
1 2
2 3
1 3
4 2
1 2
3 4	

輸出格式 & 樣例

對於每一組資料:

先輸出:"Scenario #i" ,表示第i組資料

然後如果有同性戀的輸出"Suspicious bugs found!"

否則輸出"No suspicious bugs found!"

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

解析

顯然這是一個並查集,但並不是一個裸的並查集

我們要多維護一個數組rel[],其中rel[i]表示i和它的祖先的關係(relative)。我們定義rel[i]表示兩種性別,當根節點相同且rel[]相同時,它們就是同性戀

rel[]

的更新方式:

(in Find(x))
rel[x] = (rel[x] + rel[U[x]]) % 2;
(in Union(x, y))
int fx = Find(x), fy = Find(y);
...
rel[fx] = (rel[x] + rel[y] + 1) % 2;

rel[]的判斷方式:

(in Union(x, y))
if (fx == fy) {
	if (rel[x] == rel[y]) suspiciousFound = true;
    return;
}

剩下的照常寫就行

注意路徑壓縮要分開寫,先建立一個變數存它的祖先節點再更新

按秩合併沒寫過不知道

程式碼實現

你們最喜歡的程式碼實現:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAXM = 1000000 + 10;

int n, m;
int U[MAXM], rel[MAXM];

bool flag;

int Find(int x) {
    if (x != U[x]) {
    	// 把路徑壓縮撐開寫
        int fux = Find(U[x]);
        rel[x] = (rel[x] + rel[U[x]]) % 2; // 更新rel陣列
        // 1 1 -> 0
        // 1 0 / 0 1 -> 1
        // 0 0 -> 0
        // 其實是一個異或的過程
        U[x] = fux; // qwq
    }
    return U[x];
}

void Union(int x, int y) {
    int fx = Find(x), fy = Find(y);
    if (fx == fy) {
        if (rel[x] == rel[y]) flag = true; // 判斷是否同性
        return;
    }
    U[fx] = fy;
    rel[fx] = (rel[x] + rel[y] + 1) % 2; // 更新rel陣列
}

int main(int argc, char *const argv[]) {
    int t;
    scanf("%d", &t);
    int _t = 0;
    while (t --> 0) {
        memset(U, 0, sizeof(U));
        memset(rel, 0, sizeof(rel));
        n = 0, m = 0, flag = false;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) U[i] = i;
        for (int i = 1; i <= m; ++i) {
            int x, y;
            scanf("%d %d", &x, &y);
            Union(x, y);
        }
        printf("Scenario #%d:\n", ++_t);
        if (flag) printf("Suspicious bugs found!\n");
        else printf("No suspicious bugs found!\n");
    }
    return 3; // qwq
}