一、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();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:dfs
dfs 遍歷一下圖,統計遍歷過程中的邊數 cnt 是否等於 m 即可…
複雜度分析
- 時間複雜度:,
- 空間複雜度:,