蓝桥杯 历届试题 合根植物(并查集)
傳送門
題目描述
w星球的一個種植園,被分成 m * n個小格子(東西方向m行,南北方向n列)。每個格子里種了一株合根植物。
這種植物有個特點,它的根可能會沿著南北或東西方向伸展,從而與另一個格子的植物合成為一體。
如果我們告訴你哪些小格子間出現(xiàn)了連根現(xiàn)象,你能說出這個園中一共有多少株合根植物嗎?
輸入
第一行,兩個整數(shù)m,n,用空格分開,表示格子的行數(shù)、列數(shù)(1<m,n<1000)。
接下來一行,一個整數(shù)k,表示下面還有k行數(shù)據(jù)(0<k<100000)
接下來k行,第行兩個整數(shù)a,b,表示編號為a的小格子和編號為b的小格子合根了。
格子的編號一行一行,從上到下,從左到右編號。
比如:5 * 4 的小格子,編號:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20
輸出
園中合根植物的數(shù)目
樣例輸入
5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17
樣例輸出
5
分析
- 這道題題意很明確,要求這個無向圖的圖的連通分量(連通塊數(shù)目),最先想到的是依次去遍歷每一個點,如果這個點沒有被訪問過,就用DFS(別問,問就是深搜)把這個點可到達的點全部做標(biāo)記,然后計數(shù)器加一。當(dāng)訪問完所有的點的是時候,就可以得到連通塊數(shù)目。思路很直觀,但是這個題目給的不是抽象圖,要求點的坐標(biāo)比較麻煩(因為菜),所以我們考慮另一種做法。
- 另一種做法是并查集,把連通的植物號數(shù)都加到同一個集合中,最后再計算集合的個數(shù)。做法十分簡單明了(前提是要會什么是并查集)。
并查集簡介
在計算機科學(xué)中,并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不交集(Disjoint Sets)的合并及查詢問題。
(摘自維基百科)
未經(jīng)過優(yōu)化的并查集的三個關(guān)鍵函數(shù)的偽代碼如下:
用于初始化的函數(shù):
function MakeSet(x)x.parent := x//把該元素的父節(jié)點設(shè)置為自己用該元素于查找根節(jié)點的函數(shù):
function Find(x)if x.parent == xreturn xelsereturn Find(x.parent)//沿著父節(jié)點往上爬,找根結(jié)點用于合并集合的函數(shù):
function Union(x, y)xRoot := Find(x) //找到x的根結(jié)點yRoot := Find(y) //找到y(tǒng)的根結(jié)點xRoot.parent := yRoot //把兩棵樹(集合)合并要學(xué)并查集這些肯定是不夠的,另外去找教程吧(逃
//第一次看你都不知道是啥
//第二次回來看,你就覺得這個很low
//祝你成功
代碼如下
import java.util.*; public class Main {static final int maxn=1000005;static int p[]=new int[maxn]; //數(shù)組p用于存儲i的父節(jié)點static int n,m,k;static int cnt;static void init(int num) { //初始化for(int i=0;i<=num;i++) {p[i]=i;}}static int find(int x) { //查找元素x的父節(jié)點if(p[x]==x)return x;else {p[x]=find(p[x]); //壓縮存儲return p[x];}}static void union(int x,int y) {//合并集合函數(shù)x=find(x);y=find(y);if(x==y)return ; //未進行按秩合并優(yōu)化else {p[x]=y;}}public static void main(String[] args) {Scanner cin=new Scanner(System.in);int a,b;n=cin.nextInt();m=cin.nextInt();k=cin.nextInt();init(n*m);for(int i=0;i<k;i++) {a=cin.nextInt();b=cin.nextInt();union(a, b); //把有關(guān)系的點添加到同一集合}for(int i=1;i<=n*m;i++){ //計算集合的個數(shù)if(p[i]==i)cnt++;}System.out.println(cnt);} }都說遞歸的代碼雖然簡單,是效率相對循環(huán)是較低的。于是給出了一下循環(huán)版的find函數(shù)的代碼
//這次優(yōu)化后跑快了呢
參考鏈接:
https://zh.wikipedia.org/wiki/并查集
https://www.bilibili.com/video/av7657321?from=search&seid=13766090693138965934
總結(jié)
以上是生活随笔為你收集整理的蓝桥杯 历届试题 合根植物(并查集)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蓝桥杯 历届试题 分考场(DFS+枚举)
- 下一篇: 蓝桥杯 算法训练 数字三角形(最简单的D