2017年藍橋杯國賽——合格植物,再次更新,此次直接AC了乖乖隆地動(並查集)

題目描述:

w星球的一個種植園,被分紅 m * n 個小格子(東西方向m行,南北方向n列)。每一個格子裏種了一株合根植物。
這種植物有個特色,它的根可能會沿着南北或東西方向伸展,從而與另外一個格子的植物合成爲一體。

若是咱們告訴你哪些小格子間出現了連根現象,你能說出這個園中一共有多少株合根植物嗎?
 
輸入格式
第一行,兩個整數m,n,用空格分開,表示格子的行數、列數(1<m,n<1000)。
接下來一行,一個整數k,表示下面還有k行數據(0<k<100000)
接下來k行,第行兩個整數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
 
樣例輸入
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
 
樣例說明

  

 

 

思路:並查集

那麼什麼是並查集呢?java

並查集被不少OIer認爲是最簡潔而優雅的數據結構之一,主要用於解決一些元素分組的問題。它管理一系列不相交的集合,並支持兩種操做:數組

  • 合併(Union):把兩個不相交的集合合併爲一個集合。
  • 查詢(Find):查詢兩個元素是否在同一個集合中。

固然,這樣的定義未免太過學術化,看完後恐怕不太能理解它具體有什麼用。因此咱們先來看看並查集最直接的一個應用場景:親戚問題數據結構

(洛谷P1551)親戚ide

題目背景
若某個家族人員過於龐大,要判斷兩個是不是親戚,確實還很不容易,如今給出某個親戚關係圖,求任意給出的兩我的是否具備親戚關係。
題目描述
規定:x和y是親戚,y和z是親戚,那麼x和z也是親戚。若是x,y是親戚,那麼x的親戚都是y的親戚,y的親戚也都是x的親戚。
輸入格式
第一行:三個整數n,m,p,(n<=5000,m<=5000,p<=5000),分別表示有n我的,m個親戚關係,詢問p對親戚關係。
如下m行:每行兩個數Mi,Mj,1<=Mi,Mj<=N,表示Mi和Mj具備親戚關係。
接下來p行:每行兩個數Pi,Pj,詢問Pi和Pj是否具備親戚關係。
輸出格式
P行,每行一個’Yes’或’No’。表示第i個詢問的答案爲「具備」或「不具備」親戚關係。

這實際上是一個頗有現實意義的問題。咱們能夠創建模型,把全部人劃分到若干個不相交的集合中,每一個集合裏的人彼此是親戚。爲了判斷兩我的是否爲親戚,只需看它們是否屬於同一個集合便可。所以,這裏就能夠考慮用並查集進行維護了。spa

 

AC代碼:

 1 import java.util.HashSet;
 2 import java.util.Scanner;
 3 import java.util.Set;
 4 
 5 public class MergePlant {
 6 
 7     /**
 8      * 查找
 9      * @param a 待查找的節點
10      * @param parent 存儲全部節點對應的根節點的數組
11      * @return 返回根節點的序號,從1開始
12      */
13     public static int find(int a, int[] parent) {
14         int root = a;
15         while (parent[root] != 0) {
16             root = parent[root];
17         }
18         return root;
19     }
20 
21     /**
22      * 合併
23      * @param a 合併的第一個節點
24      * @param b 合併的第二個節點
25      * @param parent 存儲根節點的數組
26      * @param rank 存儲樹的等級,最小爲0,即只有一個節點自己
27      * @return 返回 true 則表示合併成功,返回 false 則表示合併失敗,即兩個節點是在同一棵樹上
28      */
29     public static boolean union(int a, int b, int[] parent, int[] rank) {
30         int root_a = find(a, parent);
31         int root_b = find(b, parent);
32 
33         if (root_a == root_b) {
34             return false;
35         } else {
36             if (rank[root_a] > rank[root_b]) {
37                 // a節點所在的樹的等級 > b節點所在的樹的等級
38                 // 將b節點所在的樹合併到a節點所在的樹上
39                 parent[root_b] = root_a;
40             } else if (rank[root_a] < rank[root_b]) {
41                 // a節點所在的樹的等級 < b節點所在的樹的等級
42                 // 將a節點所在的樹合併到b節點所在的樹上
43                 parent[root_a] = root_b;
44             } else {
45                 // 若是相等,只需隨便選一個樹合併到另一棵樹上便可,這裏就讓a合併到b
46                 // b節點所在樹的等級要+1
47                 parent[root_a] = root_b;
48                 rank[root_b]++;
49             }
50             return true;
51         }
52     }
53 
54     /**
55      * 將全部節點的初始根節點都設置爲自身,即爲0,方便後面查找根節點
56      * 將全部樹的等級一開始都設置爲0
57      * @param parent 存儲根節點的數組
58      */
59     public static void initialization(int[] parent, int[] rank) {
60         for (int i = 0; i < parent.length; i++) {
61             parent[i] = 0;
62             rank[i] = 0;
63         }
64     }
65 
66     public static void main(String[] args) {
67         Scanner input = new Scanner(System.in);
68         int m = input.nextInt();
69         int n = input.nextInt();
70 
71         // 定義根節點數組
72         int[] parent = new int[m * n + 1];
73         // 定義樹等級數組
74         int[] rank = new int[m * n + 1];
75 
76         // initialization to -1
77         initialization(parent, rank);
78 
79         // 接收邊的數量
80         int side = input.nextInt();
81         // 接收邊,即節點與節點之間的關係
82         // 來一個關係,合併一次
83         for (int i = 0; i < side; i++) {
84             int a = input.nextInt();
85             int b = input.nextInt();
86             union(a, b, parent, rank);
87         }
88 
89         // 最後判斷存儲根節點的數組中還剩下幾棵樹,這裏用Set集合來存儲,爲了去重
90         Set<Integer> set = new HashSet<>();
91         // 編號從1 ~ m * n
92         for (int i = 1; i <= m * n; i++) {
93             set.add(find(i, parent));
94         }
95 
96         System.out.println(set.size());
97     }
98 }
相關文章
相關標籤/搜索