leetcode:684. 冗余连接(无向图)

题目来源

题目描述

在这里插入图片描述
在这里插入图片描述

题目解析

题目要求:给出一个无向图,要我们找出一条可以删去的边,使得剩余部分是一个树,如果有多个答案,则返回二维数组中最后出现的边。

类似的题目:[LeetCode] 261. Graph Valid Tree 图验证树

分析题意

一棵有n个节点的树有n - 1条边,若再加一条边,则树内必成环,题目要求我们找出这条使得树成环的边;

  • 有N个节点,要形成环的话,必须至少有N条边
  • 题目中说了只有一条多余的边,那么edges的大小必定是节点数量

这道题的关键在于:选择edges中导致结果图产生环的那条边。

这题本质就是检测图的环,有很多方法,比如并查集、拓扑排序、DFS

并查集

树是一个连通且无环的无向图,在树中多了一条附加的边之后就会出现环,因此附加的边即为导致环出现的边。

可以通过并查集寻找附加的边。初始时,每个节点都属于不同的连通分量。遍历每一条边,判断这条边连接的两个顶点是否属于相同的连通分量。

  • 如果两个顶点属于不同的连通分量,则说明在遍历到当前的边之前,这两个顶点之间不连通,因此当前的边不会导致环出现,合并这两个顶点的连通分量。

  • 如果两个顶点属于相同的连通分量,则说明在遍历到当前的边之前,这两个顶点之间已经连通,因此当前的边导致环出现,为附加的边,将当前的边作为答案返回

在这里插入图片描述

class UnionFind {
private:
    int count;
    vector<int> parent;
public:
    UnionFind(int n) : parent(n) {
        int start=1;
        count=n-start;
        for (int i=start;i<n;i++) {
            parent[i]=i;
        }
    }

    /* 查找根节点 */
    int findRoot(int x) {
        if (x!=parent[x]) {
            parent[x]=findRoot(parent[x]);
        }

        return parent[x];
    }

    /* 合并操作 */
    void unionRoot(int x, int y) {
        int root_x=findRoot(x);
        int root_y=findRoot(y);
        if (root_x != root_y) {
            parent[root_x]=root_y;
            count--;
        }
    }

    /* 判断x,y是否属于同一连通分量 */
    bool isConnect(int x, int y) {
        return findRoot(x)==findRoot(y);
    }

    /* 返回连通分量个数 */
    int getCount() {
        return count;
    }
};

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n=edges.size();
        UnionFind unionFind(n+1);

        for (auto &edge:edges) {
            int p=edge[0];
            int q=edge[1];
            if (unionFind.findRoot(p)!=unionFind.findRoot(q)) {
                unionFind.unionRoot(p,q);
            } else {
                return edge;
            }
        }

        return vector<int>{};
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值