【圖論】C_hc_樹結構判定(uf / dfs)

一、Problem

給定一個包含 N 個頂點 M 條邊的無向圖 G ,判斷 G 是不是一棵樹。

輸入

第一個是一個整數 T ,代表測試數據的組數。 (1 ≤ T ≤ 10)

每組測試數據第一行包含兩個整數 N 和 M 。(2 ≤ N ≤ 500, 1 ≤ M ≤ 100000)

以下 M 行每行包含兩個整數 a 和 b ,表示頂點 a 和頂點 b 之間有一條邊。(1 ≤ a, b ≤ N)

輸出

對於每組數據,輸出YES或者NO表示 G 是否是一棵樹。

樣例輸入
2
3 2
3 1
3 2
5 5
3 1
3 2
4 5
1 2
4 1 
樣例輸出
YES
NO

二、Solution

方法一:UF

  • 樹是一種無環的連通圖。
  • 如果並查集檢測出某一個頂點的父親和別的頂點的父親不一樣,證明這個圖是一個有環圖…

未知錯誤:😂👀

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			int T = sc.nextInt();
			while (T-- > 0) {
				int n = sc.nextInt(), m = sc.nextInt();
				if (n-1 != m) {
				    System.out.println("NO");
				    continue;
				}
				UF uf = new UF(n);
				for (int i = 0; i < m; i++) {
					int a = sc.nextInt(), b = sc.nextInt();
					uf.union(a, b);
				}
				int root = uf.find(1);
				boolean is = true;
				for (int i = 2; i<=n; i++) {
				    if (root != uf.find(i)) {
					    is = false;
					    break;
					}
				}
				System.out.println(is ? "YES" : "NO");
			}
		}
		class UF {
			int[] id, size;
			UF(int N) {
				id = new int[N+1];
				size = new int[N+1];
				for (int i = 1; i <= N; i++) {
					id[i] = i;
					size[i] = 1;
				}
			}
			int find(int p) {
				while (p != id[p]) {
					id[p] = id[id[p]];
					p = id[p];
				}
				return p;
			}
			void union(int p, int q) {
				int pID = find(p), qID = find(q);
				if (pID == qID)
					return;
				if (size[pID] > size[qID]) {
					id[qID] = pID;
					size[pID] += size[qID];
				} else {
					id[pID] = qID;
					size[qID] += size[qID];
				}
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

經檢查發現:n-1 = m 的時候,這個圖也也可能不是樹…,比如有兩個連通塊且 n-1 = m…

說白了:對樹的定義還是不太熟悉…

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			int T = sc.nextInt();
			while (T-- > 0) {
				int n = sc.nextInt(), m = sc.nextInt();
				UF uf = new UF(n);
				for (int i = 0; i < m; i++) {
					int a = sc.nextInt(), b = sc.nextInt();
					uf.union(a, b);
				}
				boolean is = true;
				if (n-1 != m) {
					is = false;
				}
				if (is) {
					int root = uf.find(1);
					for (int i = 2; i<=n; i++) {
						if (root != uf.find(i)) {
							is = false;
							break;
						}
					}
				}
				System.out.println(is ? "YES" : "NO");
			}
		}
		class UF {
			int[] id, size;
			UF(int N) {
				id = new int[N+1];
				size = new int[N+1];
				for (int i = 1; i <= N; i++) {
					id[i] = i;
					size[i] = 1;
				}
			}
			int find(int p) {
				while (p != id[p]) {
					id[p] = id[id[p]];
					p = id[p];
				}
				return p;
			}
			void union(int p, int q) {
				int pID = find(p), qID = find(q);
				if (pID == qID)
					return;
				if (size[pID] > size[qID]) {
					id[qID] = pID;
					size[pID] += size[qID];
				} else {
					id[pID] = qID;
					size[qID] += size[qID];
				}
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

複雜度分析

  • 時間複雜度:O()O()
  • 空間複雜度:O()O()

方法二:dfs

dfs 遍歷一下圖,統計遍歷過程中的邊數 cnt 是否等於 m 即可…


複雜度分析

  • 時間複雜度:O()O()
  • 空間複雜度:O()O()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章