並查集(disjoint-set forests)

來源:互聯網
上載者:User

原文地址:http://blog.csdn.net/ariesjzj/article/details/8001597

舉個簡單應用的例子。現在社交網站這麼流行,假設現在想知道兩個人之間是否存在間接好友關係(A和B為好友,B和C為好友,A和C為間接好友),有什麼好方法呢?並查集就是用於這類查詢問題的有效資料結構,正如其名(disjoint set),並查集本質上是一個集合,集合的元素為樹,因此並查集實際上表示了一個森林(disjoint-set forests)。它的特點是每棵樹中的成員都可由根結點所代表,這樣要知道兩個結點是否屬於集合的同一元素,只要看它們是否有同一“代表”。

 

邏輯很簡單,事實上原始的實現會比較慢,因為這兒的樹並不保證平衡,極端情況下樹會變成“條形”(每個結點只有一個孩子)。一般,我們會使用兩種最佳化:稱為union by rank和path compression。前者使集合在合并過程中儘可能平衡,後者使每個結點直接指向根結點,因此使查詢在常數時間完成。根據這兩種最佳化,下面是一個教科書式的實現:

int rank[100];int p[100];void makeSet(int x){p[x] = x;rank[x] = 0;}void unionSet(int x, int y){linkSet(findSet(x), findSet(y));}void linkSet(int x, int y){if (rank[x] > rank[y])  //union by rankp[y] = x;else {p[x] = y;if (rank[x] == rank[y])rank[y] = rank[y] + 1;}}int findSet(int x) {if (x != p[x])  // path compressionp[x] = findSet(p[x]);return p[x];}

 

古人云,光說不練假把式,我們來看看這個看似簡單的資料結構能解決點什麼實際問題:

RoadReconstruction(Single Round Match 356 Round 1 - Division II, Level Three)

題目並不詭異,給出一些城市間的道路,有些是好的有些是破的,如果是破的還給出修的代價,問如何以最少的代價使所有城市全連通。咋一看是圖論的最小產生樹問題,其實。。。的確可以用最小產生樹解,但這裡我們嘗試用並查集來解。注意解中利用了以下事實:初始時集合中有n棵樹,每個樹只有一個結點,自己“代表”自己。經過m輪合并,變成n-m個,經過n-1輪,合并為一個,則原森林中的所有結點全連通。

#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <algorithm>#include <string>#include <set>#include <map>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>using namespace std;typedef struct damaged_node {int cost;string id;int city1;int city2;} damaged_node;typedef struct non_damaged_node {int city1;int city2;} non_damaged_node;bool compare(const damaged_node& r1, const damaged_node& r2){return r1.cost < r2.cost;}int rank[100];int p[100];class RoadReconstruction {public:void makeSet(int x){p[x] = x;rank[x] = 0;}void unionSet(int x, int y){linkSet(findSet(x), findSet(y));}void linkSet(int x, int y){if (rank[x] > rank[y])p[y] = x;else {p[x] = y;if (rank[x] == rank[y])rank[y] = rank[y] + 1;}}int findSet(int x) {if (x != p[x])p[x] = findSet(p[x]);return p[x];}string selectReconstruction (vector <string> roads) {int n = roads.size();int i;int cno = 0;map<string, int> m;// map city name to no. in disjoint setvector<damaged_node> damaged;vector<non_damaged_node> non_damaged;vector<string> res;string ret = "";// parse the argumentsfor (i = 0; i < n; ++i) {string id, city1, city2;int cost = 0;istringstream iss(roads[i]);iss >> id >> city1 >> city2 >> cost;if (m.find(city1) == m.end())m[city1] = cno++;// generate unique id for each cityif (m.find(city2) == m.end())m[city2] = cno++;if (!cost){  // no cost, non damaged roadsnon_damaged_node t = {m[city1], m[city2]};non_damaged.push_back(t);} else {// damaged roadsdamaged_node t = {cost, id, m[city1], m[city2]};damaged.push_back(t);}}// init the disjoint setfor (i = 0; i < cno; ++i) {makeSet(i);}int cnt = 0;// reduce the disjoint set by considering non-damaged roadsfor (i = 0; i < non_damaged.size(); ++i) {int city1_no = non_damaged[i].city1;int city2_no = non_damaged[i].city2;findSet(city1_no);// update the parent, directly point to the representativefindSet(city2_no);if (p[city1_no] != p[city2_no]) {unionSet(city1_no, city2_no);cnt++;}}// try to reconstruct the damaged roads, in increasing order of costsort(damaged.begin(), damaged.end(), compare);for (i = 0; i < damaged.size(); ++i) {int city1_no = damaged[i].city1;int city2_no = damaged[i].city2;findSet(city1_no);findSet(city2_no);if (p[city1_no] != p[city2_no]) {unionSet(city1_no, city2_no);res.push_back(damaged[i].id);cnt++;}}if (cnt != cno - 1)return "IMPOSSIBLE";else {// all citys were merged into one.sort(res.begin(), res.end());for (i = 0; i < res.size(); ++i) {if (i)ret += " ";ret += res[i];}return ret;}}};

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.