leetcode 684|685. Redundant Connection 1|2

本文介绍了一种通过拓扑入度概念检测图中冗余连接的方法,并提供了两种情况下的具体实现:一种适用于无向图,另一种适用于有向图。算法通过逐条移除边并检查图的状态来确定哪条边的移除可以使图成为一个树。

684. Redundant Connection

In this problem, a tree is an undirected graph that is connected and has no cycles.

The given input is a graph that started as a tree with N nodes (with distinct values 1, 2, ..., N), with one additional edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.

The resulting graph is given as a 2D-array of edges. Each element of edges is a pair [u, v] with u < v, that represents an undirected edge connecting nodes u and v.

Return an edge that can be removed so that the resulting graph is a tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array. The answer edge [u, v] should be in the same format, with u < v.

Example 1:

Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given undirected graph will be like this:
  1
 / \
2 - 3

Example 2:

Input: [[1,2], [2,3], [3,4], [1,4], [1,5]]
Output: [1,4]
Explanation: The given undirected graph will be like this:
5 - 1 - 2
    |   |
    4 - 3

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.

使用拓扑 入度的概念 来判断是否有圈。

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) 
    {
        n = edges.size();
        vector<int> indegree(n + 1, 0);  //存每个点的入度。
        map<int, set<int>> mp;
        for (auto it : edges)
        {
            indegree[it[0]]++;
            indegree[it[1]]++;
            mp[it[0]].insert(it[1]);
            mp[it[1]].insert(it[0]);
        }
        //如果删除一条边,就是减少两个点的入度。
        for (int i = n - 1; i >= 0; i --)
        {
            indegree[edges[i][0]]--;
            indegree[edges[i][1]]--;
            mp[edges[i][0]].erase(edges[i][1]);
            mp[edges[i][1]].erase(edges[i][0]);
            
            if ( helper(indegree, mp) ) //判断是否有环 且 遍历了所有的点
                return edges[i];
            
            indegree[edges[i][0]]++;
            indegree[edges[i][1]]++;
            mp[edges[i][0]].insert(edges[i][1]);
            mp[edges[i][1]].insert(edges[i][0]); 
        }
        return vector<int>();
    }
private:    
    int n;
    
    bool helper(vector<int> indegree, map<int, set<int>> mp)
    {   
        int k = n;
        while (k)
        {
            if (find_1_indegree(indegree, mp, k) == -1)  //一次一次找入度为1的点
                return false;
            k--;
        }
        return true;
    }
    
    int find_1_indegree(vector<int> &indegree, map<int, set<int>> &mp, int leftpoint) //如果找不到入度为1的,返回 -1。找到了返回 0
    {
        for (int i = 1; i <= n; i++)
        {
            if (indegree[i] == 1)  //找到一个入度是 1 的点
            {    
                indegree[i] = 0;
                for (auto it : mp[i])  
                {
                    indegree[it]--;  //邻接所有点入度--
                    mp[it].erase(i); 
                }
                return 0;
            }
        }
        return (leftpoint == 1) ? 0 : -1; //如果只有一个点,肯定是找不到入度为1的点。因为这个都是为0。这种情况不返回 -1.
    }
};

685. Redundant Connection II

In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) for which all other nodes are descendants of this node, plus every node has exactly one parent, except for the root node which has no parents.

The given input is a directed graph that started as a rooted tree with N nodes (with distinct values 1, 2, ..., N), with one additional directed edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.

The resulting graph is given as a 2D-array of edges. Each element of edges is a pair [u, v] that represents a directed edge connecting nodes u and v, where u is a parent of child v.

Return an edge that can be removed so that the resulting graph is a rooted tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array.

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

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.

这个图是有向图,所以应该满足条件的树 应该是:

1、只有一个root,也就是最开始只有一个 入度是 0

2、去除root后,每次都能找到入度为 0 的点


class Solution {
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) 
    {
        n = edges.size();
        vector<int> indegree(n + 1, 0);  //存每个点的入度。
        map<int, set<int>> mp;
        for (auto it : edges)
        {
            indegree[it[1]]++;
            mp[it[0]].insert(it[1]);
        }
        
        //如果删除一条边,就是减少一个点的入度。
        for (int i = n - 1; i >= 0; i --)
        {
            indegree[edges[i][1]]--;
            mp[edges[i][0]].erase(edges[i][1]);
            
            if ( helper(indegree, mp) ) //判断是否只有一个root节点(入度为0的点) 且 遍历了所有的点
                return edges[i];
            
            indegree[edges[i][1]]++;
            mp[edges[i][0]].insert(edges[i][1]);
        }
        return vector<int>();
    }
private:    
    int n;
    
    bool helper(vector<int> indegree, map<int, set<int>> mp) //满足条件:最开始只有一个入度0的点,且所有点都连接上了,没有环。
    {                                                        //第一次一个点,后续起码一个。
        //第一次 单独提出来找 看是否只有一个入度为0
        int pos = 0;
        for (int i = 1; i <= n; i++)
        {   
            if (indegree[i] == 0)
            {
                if (pos != 0) //有不止一个root
                    return false;
                pos = i;
                indegree[i] = -1;
            }
        }
        for (auto it : mp[pos])  
            indegree[it]--;  //邻接所有点入度--

        //后续的 每次查找 有且只找 一个 入度为 0
        for (int i = 0; i < n - 1; i++)
        {
            if (find_1_indegree(indegree, mp) == -1)  //一次一次找入度为1的点
                return false;
        }
        return true;
    }
    
    int find_1_indegree(vector<int> &indegree, map<int, set<int>> &mp) //如果找不到入度为0的,返回 -1。找到了返回 0
    {
        for (int i = 1; i <= n; i++)
        {
            if (indegree[i] == 0)  //找到一个入度是 0 的点
            {    
                indegree[i] = -1;
                for (auto it : mp[i])  
                {
                    indegree[it]--;  //邻接所有点入度-- 
                }
                return 0;
            }
        }
        return -1; 
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值