思考: 1.甚麼是Redundant Connection(多餘的連結),在一個Graphs中去除這條邊也能形成連通圖 2.利用Union-find 3.分為 Union_set 和 find_set Union_set : 用來檢測這一條邊的兩個點a, b是不是有同一個父點(根節點),如果是則產生cycle 如果不是則設定b來自於a find_set : 設定來源的點的父點(根節點)為誰 ```c++= class Solution { public: vector <int> parent; int find_parent(int a){ if(a == parent[a]){ //目前父節點就是自己 return parent[a]; }else{ //追朔到最上層的父節點 parent[a] = find_parent(parent[a]); return parent[a]; } } bool Union(int a, int b){ a = find_parent(a); b = find_parent(b); if(a == b){ //代表有相同父節點, 這條邊加上去會形成cycle return true; }else{ //代表沒有相同父節點, b來源於a parent[b] = a; return false; } } vector<int> findRedundantConnection(vector<vector<int>>& edges) { //利用Union set來找到多餘的那條邊 //主要是每一個節點的父節點 //如果出現一條邊的a, b點都有相同父節點, 代表加入這條邊就會造成cycle int n = edges.size(); //初始化每個節點的parant都是自己 //<= 是因為 點從 1 開始 for(int i = 0; i <= n; i++){ parent.push_back(i); } //開始掃描每一條邊 for(vector<int> edge : edges){ if(Union(edge[0], edge[1])){ for(int i : parent){ printf("%d", i); } return {edge[0], edge[1]}; } } return {-1,-1}; } }; ``` ```c++= class Solution { vector<int> parent; // 儲存點的父點 int find_set(int v) { if (v == parent[v]) // 如果點的父點是自己,說明找到這個集合的根結點 return v; return parent[v] = find_set(parent[v]); // 路徑壓縮,將節點直接連接到"根"節點,提高查找效率 } bool union_set(int a, int b) { a = find_set(a); // 找節點a所屬的集合的根結點 b = find_set(b); // 找節點b所屬的集合的根結點 if (a == b) // 如果a和b的根結點相同,說明a,b已經在同一個集合中,加入這條邊會造成迴路 return true; parent[b] = a; // 否則, 將b的父節點連接到a的父節點合併集合 return false; } public: vector<int> findRedundantConnection(vector<vector<int>>& edges) { int n = edges.size(); for (int i = 0; i <= n; i++) parent.push_back(i); // 初始化,每一個節點的父親都預設為自己 for (vector<int> edge : edges) { if (union_set(edge[0], edge[1])) // 嘗試將兩個節點合併到同一個集合內 return {edge[0], edge[1]}; // 如果這條節點會形成迴圈則代表是多餘的 } return {-1, -1}; // 如果跑完全部的節點都沒找到形成迴路的邊,代表無 } }; //預設每一個點的父節點都是自己 //1 2 3 //1 2 3 // //[1,2] ->檢查 1 和 2 的父節點 1是1, 2是2, 則 2的父節點為 1 //[1,3] ->檢查 1 和 3 的父節點 1是1, 3是3, 則 3的父節點為 1 //[2,3] ->檢查 2 和 3 的父節點 2是1, 3是1, 則true 此邊為reduentent connection ```