日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蓝桥杯 历届试题 合根植物(并查集)

發(fā)布時(shí)間:2025/3/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯 历届试题 合根植物(并查集) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

傳送門

題目描述

w星球的一個(gè)種植園,被分成 m * n個(gè)小格子(東西方向m行,南北方向n列)。每個(gè)格子里種了一株合根植物。
這種植物有個(gè)特點(diǎn),它的根可能會沿著南北或東西方向伸展,從而與另一個(gè)格子的植物合成為一體。
如果我們告訴你哪些小格子間出現(xiàn)了連根現(xiàn)象,你能說出這個(gè)園中一共有多少株合根植物嗎?

輸入

第一行,兩個(gè)整數(shù)m,n,用空格分開,表示格子的行數(shù)、列數(shù)(1<m,n<1000)。
接下來一行,一個(gè)整數(shù)k,表示下面還有k行數(shù)據(jù)(0<k<100000)
接下來k行,第行兩個(gè)整數(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


分析

  • 這道題題意很明確,要求這個(gè)無向圖的圖的連通分量(連通塊數(shù)目),最先想到的是依次去遍歷每一個(gè)點(diǎn),如果這個(gè)點(diǎn)沒有被訪問過,就用DFS(別問,問就是深搜)把這個(gè)點(diǎn)可到達(dá)的點(diǎn)全部做標(biāo)記,然后計(jì)數(shù)器加一。當(dāng)訪問完所有的點(diǎn)的是時(shí)候,就可以得到連通塊數(shù)目。思路很直觀,但是這個(gè)題目給的不是抽象圖,要求點(diǎn)的坐標(biāo)比較麻煩(因?yàn)椴?#xff09;,所以我們考慮另一種做法。
  • 另一種做法是并查集,把連通的植物號數(shù)都加到同一個(gè)集合中,最后再計(jì)算集合的個(gè)數(shù)。做法十分簡單明了(前提是要會什么是并查集)。

并查集簡介

在計(jì)算機(jī)科學(xué)中,并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不交集(Disjoint Sets)的合并及查詢問題。
(摘自維基百科)

未經(jīng)過優(yōu)化的并查集的三個(gè)關(guān)鍵函數(shù)的偽代碼如下:

用于初始化的函數(shù)

function MakeSet(x)x.parent := x//把該元素的父節(jié)點(diǎn)設(shè)置為自己

用該元素于查找根節(jié)點(diǎn)的函數(shù)

function Find(x)if x.parent == xreturn xelsereturn Find(x.parent)//沿著父節(jié)點(diǎn)往上爬,找根結(jié)點(diǎn)

用于合并集合的函數(shù)

function Union(x, y)xRoot := Find(x) //找到x的根結(jié)點(diǎn)yRoot := Find(y) //找到y(tǒng)的根結(jié)點(diǎn)xRoot.parent := yRoot //把兩棵樹(集合)合并

要學(xué)并查集這些肯定是不夠的,另外去找教程吧(逃
//第一次看你都不知道是啥
//第二次回來看,你就覺得這個(gè)很low
//祝你成功

代碼如下

import java.util.*; public class Main {static final int maxn=1000005;static int p[]=new int[maxn]; //數(shù)組p用于存儲i的父節(jié)點(diǎn)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é)點(diǎn)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 ; //未進(jìn)行按秩合并優(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)系的點(diǎn)添加到同一集合}for(int i=1;i<=n*m;i++){ //計(jì)算集合的個(gè)數(shù)if(p[i]==i)cnt++;}System.out.println(cnt);} }

都說遞歸的代碼雖然簡單,是效率相對循環(huán)是較低的。于是給出了一下循環(huán)版的find函數(shù)的代碼
//這次優(yōu)化后跑快了呢

static int find(int x) {int t,q=x;while(p[x]!=x) {x=p[x];}//把x到根結(jié)點(diǎn)路徑上的元素的父節(jié)點(diǎn)全部變?yōu)楦Y(jié)點(diǎn)while(q!=x) {t=p[q];p[q]=x;q=t;}return x;}

參考鏈接:
https://zh.wikipedia.org/wiki/并查集
https://www.bilibili.com/video/av7657321?from=search&seid=13766090693138965934

總結(jié)

以上是生活随笔為你收集整理的蓝桥杯 历届试题 合根植物(并查集)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。