[NOIP模擬賽][分層圖][狀態壓縮] 密室
阿新 • • 發佈:2020-09-17
https://leetcode-cn.com/problems/redundant-connection-ii/
對於有向圖的樹,如果增加一條有向邊,則會出現兩種情況
第一種為形成一個點有兩個father
1.有有向環,無環
第二種為有環
class Solution { private: static const int N = 1010; // 如題:二維陣列大小的在3到1000範圍內 int father[N]; int n; // 邊的數量 // 並查集初始化 void init() { for (int i = 1; i <= n; ++i) { father[i] = i; } } // 並查集裡尋根的過程 int find(int u) { return u == father[u] ? u : father[u] = find(father[u]); } // 將v->u 這條邊加入並查集 void join(int u, int v) { u = find(u); v = find(v); if (u == v) return ; father[v] = u; } // 判斷 u 和 v是否找到同一個根 bool same(int u, int v) { u = find(u); v = find(v); return u == v; } // 在有向圖裡找到刪除的那條邊,使其變成樹 vector<int> getRemoveEdge(const vector<vector<int>>& edges) { init(); // 初始化並查集 for (int i = 0; i < n; i++) { // 遍歷所有的邊 if (same(edges[i][0], edges[i][1])) { // 構成有向環了,就是要刪除的邊 return edges[i]; } join(edges[i][0], edges[i][1]); } return {}; } // 刪一條邊之後判斷是不是樹 bool isTreeAfterRemoveEdge(const vector<vector<int>>& edges, int deleteEdge) { init(); // 初始化並查集 for (int i = 0; i < n; i++) { if (i == deleteEdge) continue; if (same(edges[i][0], edges[i][1])) { // 構成有向環了,一定不是樹 return false; } join(edges[i][0], edges[i][1]); } return true; } public: vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) { int inDegree[N] = {0}; // 記錄節點入度 n = edges.size(); // 邊的數量 for (int i = 0; i < n; i++) { inDegree[edges[i][1]]++; // 統計入度 } vector<int> vec; // 記錄入度為2的邊(如果有的話就兩條邊) // 找入度為2的節點所對應的邊,注意要倒敘,因為優先返回最後出現在二維陣列中的答案 for (int i = n - 1; i >= 0; i--) { if (inDegree[edges[i][1]] == 2) { vec.push_back(i); } } // 處理圖中情況1 和 情況2 // 如果有入度為2的節點,那麼一定是兩條邊裡刪一個,看刪哪個可以構成樹 if (vec.size() > 0) { if (isTreeAfterRemoveEdge(edges, vec[0])) { return edges[vec[0]]; } else { return edges[vec[1]]; } } // 處理圖中情況3 // 明確沒有入度為2的情況,那麼一定有有向環,找到構成環的邊返回就可以了 return getRemoveEdge(edges); } }; 作者:carlsun-2 連結:https://leetcode-cn.com/problems/redundant-connection-ii/solution/685-rong-yu-lian-jie-iibing-cha-ji-de-ying-yong-xi/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。