leetcode685. 冗余连接 II/并查集

题目:685. 冗余连接 II

在本问题中,有根树指满足以下条件的有向图。该树只有一个根节点,所有其他节点都是该根节点的后继。每一个节点只有一个父节点,除了根节点没有父节点。

输入一个有向图,该图由一个有着N个节点 (节点值不重复1, 2, …, N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。

结果图是一个以边组成的二维数组。 每一个边 的元素是一对 [u, v],用以表示有向图中连接顶点 u 和顶点 v 的边,其中 u 是 v 的一个父节点。

返回一条能删除的边,使得剩下的图是有N个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。

示例 1:

输入: [[1,2], [1,3], [2,3]]
输出: [2,3]
解释: 给定的有向图如下:
  1
 / \
v   v
2-->3

示例 2:

输入: [[1,2], [2,3], [3,4], [4,1], [1,5]]
输出: [4,1]
解释: 给定的有向图如下:
5 <- 1 -> 2
     ^    |
     |    v
     4 <- 3

注意:

  • 二维数组大小的在3到1000范围内。
  • 二维数组中的每个整数在1到N之间,其中 N 是二维数组的大小。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/redundant-connection-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

基本思想:并查集

参考链接:https://leetcode-cn.com/problems/redundant-connection-ii/solution/685-rong-yu-lian-jie-iibing-cha-ji-de-ying-yong-xi/
在做本题的时候,首先要想明白,什么情况下会出现附加边

  • 图中存在环的时候
  • 图中有入度为2的节点的时候

利用并查集来判断图中是否有环:当该条边还未加入并查集的时候,就已经有相同的根,那么该条边就是导致图中有环的边。

class Union{
    
    
public:
    vector<int> parent;
    vector<int> level;
    Union(){
    
    
        parent = vector<int>(1010, 0);
        level = vector<int>(1010, 0);
    }
    int find(int x){
    
    //查找当前节点的根节点
        int p = x;
        while(parent[p] != 0){
    
    
            p = parent[p];
        }
        return p;
    }
    
    void merge(int x, int y){
    
    //归并两个节点
        int px = find(x);
        int py = find(y);
        if(level[px] > level[py]){
    
    
            parent[py] = px;
        }
        else if(level[px] < level[py]){
    
    
            parent[px] = py;
        }
        else{
    
    
            parent[px] = py;
            level[py]++;
        }
    }
    
    bool same(int x, int y){
    
    //判断两个节点是否有相同的父亲
        int px = find(x);
        int py = find(y);
        return px == py;
    }
};
class Solution {
    
    
public:
    //判断能否构成一棵树
    bool isTree(vector<vector<int>>& edges, int k){
    
    
        Union U;
        for(int i = 0; i < edges.size(); ++i){
    
    
            if(i == k)
                continue;
            if(U.same(edges[i][0], edges[i][1])){
    
    
                return false;
            }
            U.merge(edges[i][0], edges[i][1]);
        }
        return true;
    }
    
    //确定删除环中的哪一条边
    vector<int> getEdges(vector<vector<int>>& edges){
    
    
        Union U;
        for(int i = 0; i < edges.size(); ++i){
    
    
            if(U.same(edges[i][0], edges[i][1])){
    
    
                return edges[i];
            }
            U.merge(edges[i][0], edges[i][1]);
        }
        return {
    
    };
    }
    
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
    
    
        //本题利用并查集的思想
        //分两种情况进行考虑
        //图中有环
        //图中没有环,但是有入度为2的点
        
        
        //统计点的入度
        int n = edges.size();
        vector<int> indegree(n + 1, 0);
        
        for(auto e : edges){
    
    
            indegree[e[1]]++;
        }
        
        vector<int> vec;
        for(int i = n - 1; i >= 0; --i){
    
    
            if(indegree[edges[i][1]] == 2){
    
    
                vec.push_back(i);
            }
        }
        
        //如果有度为2的点,判断删除后是否会构成树
        if(vec.size() > 0){
    
    
            if(isTree(edges, vec[0])){
    
    
                return edges[vec[0]];
            }
            else{
    
    
                return edges[vec[1]];
            }
        }
        
        return getEdges(edges);
    }
};

猜你喜欢

转载自blog.csdn.net/qq_31672701/article/details/108651921
今日推荐