並查集應用總結
一.並查集的概念
並查集是一種演算法可以用來判斷相互關聯(同屬一個集合)的元素屬於幾個集合,也可以用來判斷圖結構中的兩點是否是聯通的。並查集的設計思路是這樣的:
在程式執行過程中任意元素一定輸於以下三種狀態
1.即f[i]=i,在該種狀態下的元素可能是未被合併(初始狀態),也可能是經過合併但是選擇的父節點就是這個節點
2.已有父節點並且就是當前狀態下真正的父節點(其實是最正常的狀態,第二種狀態也包含第一種情況)。
3.已有父節點但並非當前狀態下真正的父節點,可能是以前的父節點,由merge函式可以看出,當合並兩個節點時只是合併兩個節點的父節點,當這個節點的父節點不是本身的時候這個節點的父節點就不會被更改成新的父節點,這種狀態在統計集合數量的時候是危險的,因為回使得集合數量增多,但其實並不用擔心這個問題,仔細考察getf函式(查詢父節點)的時候就會發現f[a]=getf(f[a])這樣一段程式碼,原來getf函式不僅返回了每個節點的父親,還順便修改了每個節點的f[]值使它和他父親的f[]值一致,所以每當該節點或這個節點的子節點被merge再次合併地時候,這個節點的f[]就會被修改成正確值,但是問題就來了,萬一該節點沒有被再次合併怎麼辦?保險一點的操作應該是在merge完所有的節點之後再getf以下所有的節點,這樣所有的節點就正確了。
二.並查集的應用
1.用來合併集合元素,並確定結合數量,查尋元素屬於哪個集合。
2.在圖結構裡(圖裡的點便是元素),確定兩點是否處於聯通狀態,應用舉例:
(1)Kruskal法最小生成樹
思路:將所有的邊依照長度大小排序,依次從小到大進行行選澤,每次選中一邊,就將邊兩端的點用並查集合並,如果選擇的邊經並查集查詢已經聯通,那麼跳過這條邊
問題
資料
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
程式碼
//
// main.cpp
// 圖的最小生成樹之kruskal演算法
//
// Created by 張嘉韜 on 16/3/18.
// Copyright ? 2016年 張嘉韜. All rights reserved.
//
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int f[50];
struct line
{
int u;
int v;
int w;
}lines[50];
int cmp(const void *a,const void *b)
{
return (*(line *)a).w>(*(line *)b).w?1:-1;
}
void init(int n)
{
for(int i=1;i<=n;i++) f[i]=i;
}
int getf(int a)
{
if(f[a]==a) return a;
else
{
f[a]=getf(f[a]);
return f[a];
}
}
int merge(int a,int b)
{
int t1,t2;
t1=getf(a);
t2=getf(b);
if(t1!=t2)
{
f[t2]=t1;
return 1;
}
else return 0;
}
int main(int argc, const char * argv[]) {
freopen("/Users/zhangjiatao/Desktop/input.txt","r",stdin);
int n,m,sum;
sum=0;
cin>>n>>m;
init(n);
for(int i=0;i<=m-1;i++)
{
cin>>lines[i].u>>lines[i].v>>lines[i].w;
}
qsort(lines,m,sizeof(lines[0]),cmp);
for(int i=0;i<=m-1;i++) cout<<lines[i].w<<" ";
cout<<endl;
for(int i=0;i<=m-1;i++)
{
if(merge(lines[i].u,lines[i].v)==1)
{
sum+=lines[i].w;
cout<<i+1<<" ";
}
}
cout<<endl;
cout<<sum<<endl;
return 0;
}
三.並查集的模板
1.問題
2.輸入
#include <iostream>
#include <cstring>
using namespace std;
int f[50];
void init(int n)
{
for(int i=1;i<=n;i++) f[i]=i;
}
int getf(int a)
{
if(f[a]==a) return a;
else
{
f[a]=getf(f[a]);
return f[a];
}
}
void merge(int a,int b)
{
int t1,t2;
t1=getf(a);
t2=getf(b);
if(t1!=t2)
{
f[t2]=t1;
}
}
void print(int n)
{
for(int i=1;i<=n;i++) cout<<"("<<i<<")"<<f[i]<<" ";
cout<<endl;
}
int main(int argc, const char * argv[]) {
freopen("/Users/zhangjiatao/Desktop/input.txt","r",stdin);
int n,m,a,b,sum;
sum=0;
cin>>n>>m;
init(n);
for(int i=1;i<=m;i++)
{
cin>>a>>b;
merge(a,b);
print(n);
}
for(int i=1;i<=n;i++)
{
f[i]=getf(i);
}
for(int i=1;i<=n;i++)
if(f[i]==i) sum++;
cout<<sum<<endl;
return 0;
}
10 8
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
相關文章
- 並查集應用並查集
- 並查集(UnionFind)技巧總結並查集
- 並查集深度應用並查集
- 並查集的應用2並查集
- 並查集(二)並查集的演算法應用案例上並查集演算法
- 並查集擴充套件應用並查集套件
- 並查集的簡單應用並查集
- 【學習筆記】並查集應用筆記並查集
- 並查集經典應用場景並查集
- 【帶權並查集】理論和應用並查集
- 資料結構-並查集資料結構並查集
- 並查集在實際問題中的應用並查集
- 並查集到帶權並查集並查集
- 資料結構之並查集資料結構並查集
- 查並集
- 資料結構:速通並查集資料結構並查集
- 【資料結構】帶權並查集資料結構並查集
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 並查集(一)並查集的幾種實現並查集
- Mybatis 查詢語句結果集總結MyBatis
- 3.1並查集並查集
- 並查集(小白)並查集
- [leetcode] 並查集(Ⅱ)LeetCode並查集
- [leetcode] 並查集(Ⅲ)LeetCode並查集
- [leetcode] 並查集(Ⅰ)LeetCode並查集
- 優雅的資料結構–並查集資料結構並查集
- 資料結構與演算法知識點總結(3)樹、圖與並查集資料結構演算法並查集
- 並查集演算法Union-Find的思想、實現以及應用並查集演算法
- 資料結構——並查集 學習筆記資料結構並查集筆記
- 淺談並查集並查集
- 食物鏈(並查集)並查集
- 並查集跳躍並查集
- 各種並查集並查集
- 寫模板, 並查集。並查集
- 並查集(Union Find)並查集
- The Door Problem 並查集並查集
- 並查集練習並查集
- 並查集的使用並查集
- 演算法與資料結構之並查集演算法資料結構並查集