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:
使用拓扑 入度的概念 来判断是否有圈。
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:
这个图是有向图,所以应该满足条件的树 应该是:
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;
}
};
本文介绍了一种通过拓扑入度概念检测图中冗余连接的方法,并提供了两种情况下的具体实现:一种适用于无向图,另一种适用于有向图。算法通过逐条移除边并检查图的状态来确定哪条边的移除可以使图成为一个树。
357

被折叠的 条评论
为什么被折叠?



