LeetCode 685. 冗余连接 II

博主 910 2020-09-17

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

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

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

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

image.png

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


自己写的超时代码,最后给了一个很长的案例,导致超时,不过结果是对的:

class Solution {
private:
    int inDegree[1005]; // 统计1~N节点的入度
    bool point[1005][1005];
    bool visit[1005] = {0};
    vector<int> oneDegreeNode;
    int N;
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        N = (int)edges.size(); // N个节点
        for (int i = 0; i < N; ++i) {
            inDegree[edges[i][1]]++;
            point[edges[i][0]][edges[i][1]] = true;
        }
        int root = -1;
        for (int i = 1; i <= N; ++i) {
            if (inDegree[i] == 0) {// 节点i没有入度 则此节点一定为根节点
                root = i;
                break;
            }else if (inDegree[i] == 1){
                oneDegreeNode.push_back(i);
            }
        }
        if (root != -1) {// 找到了根节点
            // 依次删去所有的边,从root进行dfs
            for (int i = N - 1; i >= 0; --i) {
                point[edges[i][0]][edges[i][1]] = false;
                fill(visit, visit+N+1, false);
                dfs(root);
                // 如果dfs遍历到了所有节点,说明现在删去的边正确
                bool getAns = true;
                for (int j = 1; j <= N; ++j) {
                    if (visit[j] == false) {
                        getAns = false;
                        break;
                    }
                }
                if (getAns == true) {
                    return vector<int>({edges[i][0], edges[i][1]});
                }
                point[edges[i][0]][edges[i][1]] = true;
            }
        }else{
            // 没找到根节点 需要从oneDegreeNode中查找
            for (root = oneDegreeNode[0]; root < oneDegreeNode.size(); ++root) {
                for (int i = N - 1; i >= 0; --i) {
                    if (edges[i][1] == root) {
                        point[edges[i][0]][edges[i][1]] = false;
                        fill(visit, visit+N+1, false);
                        dfs(root);
                        // 如果dfs遍历到了所有节点,说明现在删去的边正确
                        bool getAns = true;
                        for (int j = 1; j <= N; ++j) {
                            if (visit[j] == false) {
                                getAns = false;
                                break;
                            }
                        }
                        if (getAns == true) {
                            return vector<int>({edges[i][0], edges[i][1]});
                        }
                        point[edges[i][0]][edges[i][1]] = true;
                    }
                }
            }
        }
        return vector<int>();
        
    }
    
    void dfs(int pos){
        visit[pos] = true;
        for (int k = 1; k <= N; ++k) {
            if (point[pos][k] == true && visit[k] == false) {
                dfs(k);
            }
        }
    }
    
    
};

解题的答案记录一下:
image.png
image.png

struct UnionFind {
    vector <int> ancestor;

    UnionFind(int n) {
        ancestor.resize(n);
        for (int i = 0; i < n; ++i) {
            ancestor[i] = i;
        }
    }

    int find(int index) {
        return index == ancestor[index] ? index : ancestor[index] = find(ancestor[index]);
    }

    void merge(int u, int v) {
        ancestor[find(u)] = find(v);
    }
};

class Solution {
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        int nodesCount = edges.size();
        UnionFind uf = UnionFind(nodesCount + 1);
        auto parent = vector<int>(nodesCount + 1);
        for (int i = 1; i <= nodesCount; ++i) {
            parent[i] = i;
        }
        int conflict = -1;
        int cycle = -1;
        for (int i = 0; i < nodesCount; ++i) {
            auto edge = edges[i];
            int node1 = edge[0], node2 = edge[1];
            if (parent[node2] != node2) {
                conflict = i;
            } else {
                parent[node2] = node1;
                if (uf.find(node1) == uf.find(node2)) {
                    cycle = i;
                } else {
                    uf.merge(node1, node2);
                }
            }
        }
        if (conflict < 0) {
            auto redundant = vector<int> {edges[cycle][0], edges[cycle][1]};
            return redundant;
        } else {
            auto conflictEdge = edges[conflict];
            if (cycle >= 0) {
                auto redundant = vector<int> {parent[conflictEdge[1]], conflictEdge[1]};
                return redundant;
            } else {
                auto redundant = vector<int> {conflictEdge[0], conflictEdge[1]};
                return redundant;
            }
        }
    }
};