力扣每日一题 685. 冗余连接 II

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

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

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

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

简单来说就是有n个节点n条边的有向图,需要找到最后加入的一条删除后可以构成有向树的边。

今天这题目比昨天的难不少,或者说复杂不少,因为需要分情况考虑了,昨天的代码直接贴过来都会有测试用例过不去。

显然,一棵由有向图构成的树在增加一条边之后,会有两种可能。第一种情况,新增的边连接了根节点,不存在入度为0的根节点了。第二种情况,新增的边连接的两个非根节点,出现了一个入度为2的节点。

对于第一种情况,和昨天的做法是一样的,一条条加边,找到一条连接的两个点在同一个联通分量的边就可以返回了。

但对于第二种情况,我们需要找到那两条指向了同一个节点的边,然后尝试删除一条边,判断是否构成树。

cpp 复制代码
class Solution {
public:
    int find(int x)
    {
        if (tree[x] == x) return x;
        return find(tree[x]);
    }
    void unite(int x, int y)
    {
        int fx = find(x), fy = find(y);
        tree[fy] = fx;
    }
    bool isTree(vector<vector<int>>& edges, int ii)
    {
        const int n = edges.size();
        tree.resize(n+1);
        for (int i=1; i<=n; ++i) tree[i] = i;
        for (int i=0; i<n; ++i)
        {
            if (i == ii) continue;
            if (find(edges[i][0]) != find(edges[i][1]))
            {
                unite(edges[i][0], edges[i][1]);
            }
            else return false;
        }
        return true;
    }
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        const int n = edges.size();
        int inDgree[n+1]; //记录入度
        int multi = 0;
        for (int i=1; i<=n; ++i) inDgree[i]=0;
        for (auto i:edges)
        {
            inDgree[i[1]]++;
            if (inDgree[i[1]] == 2) multi = i[1]; // 找到入度为2的点,保证最多只有一个
        }
        if (multi != 0) // 如果存在入度为2的点
        {
            for (int i=n-1; i>=0; --i)
            {
                if (edges[i][1] == multi) // 从后往前尝试删除指向的边
                {
                    if (isTree(edges, i)) // 如果后加入的边删除后构成树,那么就直接返回这条边即可
                    {
                        return edges[i];
                    }
                    else // 如果后加入的删除后无法构成树,那要删除的一定是先加入的那条边
                    {
                        while (--i)
                        {
                            if (edges[i][1] == multi)
                            {
                                return edges[i];
                            }
                        }
                    }
                }
            }
        }
        else // 没有入度为2的点,处理方法与昨天一致
        {
            tree.resize(n+1);
            for (int i=1; i<=n; ++i) tree[i] = i;
            for (int i=0; i<n; ++i)
            {
                if (find(edges[i][0]) != find(edges[i][1]))
                {
                    unite(edges[i][0], edges[i][1]);
                }
                else return edges[i];
            }
        }
        return edges[0];
    }
private:
    vector<int> tree;
};
相关推荐
周杰伦_Jay1 小时前
【 RocketMQ 全解析】分布式消息队列的架构、消息转发与快速实践、事务消息
分布式·算法·架构·rocketmq·1024程序员节
sprintzer1 小时前
10.16-10.25力扣计数刷题
算法·leetcode
王哈哈^_^2 小时前
【数据集】【YOLO】【目标检测】建筑垃圾数据集 4256 张,YOLO建筑垃圾识别算法实战训推教程。
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·数据集
CoovallyAIHub2 小时前
不看异常,怎么学会识别异常?用“异常”指导异常检测!——NAGL方法解析(附代码地址)
深度学习·算法·计算机视觉
共享家95272 小时前
数据结构-并查集
数据结构·c++·算法
IT古董3 小时前
【第五章:计算机视觉-项目实战之推荐/广告系统】2.粗排算法-(2)理解粗排模型之离线部分:双塔模型结构精讲及实现
人工智能·算法·计算机视觉
茉莉玫瑰花茶3 小时前
贪心 - 后篇
算法
m0_748233643 小时前
【C++篇】C++11入门:踏入C++新世界的大门
java·c++·算法
lxmyzzs3 小时前
【图像算法 - 31】基于深度学习的太阳能板缺陷检测系统:YOLOv12 + UI界面 + 数据集实现
人工智能·深度学习·算法·yolo·缺陷检测
lxmyzzs3 小时前
【图像算法 - 32】基于深度学习的风力发电设备缺陷检测系统:YOLOv12 + UI界面 + 数据集实现
深度学习·算法·yolo·计算机视觉