zoukankan      html  css  js  c++  java
  • 685. Redundant Connection II

    问题:

    684. Redundant Connection

    的第二版本,由原来的无向图->有向图

    那么给定一组edge [u,v],定义从顶点u到v的连线,构成有向图。parent[v]=u,u->v

    求最后一个多余出来的[u,v],使得出现了回环。(若没有这个连线,则可形成tree)

    Example 1:
    Input: [[1,2], [1,3], [2,3]]
    Output: [2,3]
    Explanation: The given directed graph will be like this:
      1
     / 
    v   v
    2-->3
    
    Example 2:
    Input: [[1,2], [2,3], [3,4], [4,1], [1,5]]
    Output: [4,1]
    Explanation: The given directed graph will be like this:
    5 <- 1 -> 2
         ^    |
         |    v
         4 <- 3
    
    Example 3:
    Input: [[2,1],[3,1],[4,2],[1,4]]
    Output: [2,1]
    Explanation: The given directed graph will be like this:
    1 <- 2 
    ↑ ↘︎ ↑  
    3    4 
    
    Note:
    The size of the input 2D-array will be between 3 and 1000.
    Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array.
    

    解法:并查集(Disjoint Set)

    与无向图的区别:

    • 父子关系明确

    因此,要成为tree,除了不能形成环cycle之外,对每一个节点,还只能有一个parent节点。

    例如,

    • Example的 1:节点3 就有 两个parent:1 和 2 ([1,3], [2,3])
    • Example的 2:节点1 就有 两个parent:2 和 3 ([2,1], [3,1])

    所以,我们在原先无向图的求解之前,

    增加判断parent节点个数的逻辑。

    这里增加parent数组,表示每个节点的父节点。

    ⚠️ 注意:这里不是Disjoint Set类里的表示每个节点root的辅助变量。是本问题特殊增加。

    遍历edges,对每个[u, v],更新parent[v]=u

    然后,在每次更新之前,判断是否parent[v]已经被赋值,若被赋值了,则我们要返回的最终结果,有可能是:

    • candidate_res1:之前赋值的那个边:[parent[v], v]
    • candidate_res2: or 当前的边:[u, v]

    这里说明,节点v有两个parent。若两条边都在,那么一定不能构成tree。

    然后,我们带着这两个可能的结果,去尝试和无向图一样的环cycle的判断逻辑。

    我们先假设res2不正确,删除res2的边。去进行尝试。

    • 若出现环:
      • 证明我们删错了,结果应该是res1。
      • or 刚才的parent判断中,根本没有出现一个节点有两个parent的情况,那么直接返回当前出现环的边。(和无向图的一样)
    • 若没有出现环:
      • 证明我们删对了,结果就是res2。

    代码参考:

     1 class Solution {
     2 public:
     3     vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
     4         vector<int> candidate_res1, candidate_res2;
     5         vector<int> parent(edges.size(),-1);
     6         //find duplicated root point
     7         for(int i=0; i<edges.size(); i++) {
     8             int p1 = edges[i][0], p2 = edges[i][1];
     9             if(parent[p2-1] != -1) {//p2 has already had a parent
    10                 candidate_res1 = {parent[p2-1], p2};
    11                 candidate_res2 = {p1, p2};
    12                 //delete res2
    13                 edges[i][0] = -1;
    14                 edges[i][1] = -1;
    15                 break;
    16             }
    17             parent[p2-1]=p1;
    18         }
    19         DisjointSet DS(edges.size());
    20         for(int i=0; i<edges.size(); i++) {
    21             int p1 = edges[i][0], p2 = edges[i][1];
    22             if(p1==-1 || p2==-1) continue;
    23             if(false == DS.merge(p1-1, p2-1)) {//cycle is found
    24                 return candidate_res1.empty()?edges[i]:candidate_res1;
    25             }
    26         }
    27         return candidate_res2;
    28     }
    29 };

    附:DisjointSet的代码参考:

     1 class DisjointSet {
     2 public:
     3     DisjointSet(int n):parent(n), rank(n, 0) {
     4         for(int i=0; i<n; i++) parent[i] = i;
     5     }
     6     int find(int i) {
     7         if(parent[i] != i) {
     8             parent[i] = find(parent[i]);
     9         }
    10         return parent[i];
    11     }
    12     bool merge(int x, int y) {
    13         int x_root = find(x);
    14         int y_root = find(y);
    15         if(x_root == y_root) return false;
    16         if(rank[x_root] < rank[y_root]) {
    17             parent[x_root] = y_root;
    18         } else if(rank[y_root] < rank[x_root]) {
    19             parent[y_root] = x_root;
    20         } else {
    21             parent[x_root] = y_root;
    22             y_root++;
    23         }
    24         return true;
    25     }
    26 private:
    27     vector<int> parent;
    28     vector<int> rank;
    29 };
  • 相关阅读:
    attr与prop
    Django框架学习
    库的操作
    javascript 基础知识
    进程
    正则表达式
    模块( collections , time , random , os , sys)
    内置函数
    生成器
    迭代器
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13460071.html
Copyright © 2011-2022 走看看