文章目录
题目:685. 冗余连接 II
在本问题中,有根树指满足以下条件的有向图。该树只有一个根节点,所有其他节点都是该根节点的后继。每一个节点只有一个父节点,除了根节点没有父节点。
输入一个有向图,该图由一个有着N个节点 (节点值不重复1, 2, …, N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。
结果图是一个以边组成的二维数组。 每一个边 的元素是一对 [u, v],用以表示有向图中连接顶点 u 和顶点 v 的边,其中 u 是 v 的一个父节点。
返回一条能删除的边,使得剩下的图是有N个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。
示例 1:
输入: [[1,2], [1,3], [2,3]]
输出: [2,3]
解释: 给定的有向图如下:
1
/ \
v v
2-->3
示例 2:
输入: [[1,2], [2,3], [3,4], [4,1], [1,5]]
输出: [4,1]
解释: 给定的有向图如下:
5 <- 1 -> 2
^ |
| v
4 <- 3
注意:
- 二维数组大小的在3到1000范围内。
- 二维数组中的每个整数在1到N之间,其中 N 是二维数组的大小。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/redundant-connection-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
基本思想:并查集
参考链接:https://leetcode-cn.com/problems/redundant-connection-ii/solution/685-rong-yu-lian-jie-iibing-cha-ji-de-ying-yong-xi/
在做本题的时候,首先要想明白,什么情况下会出现附加边
- 图中存在环的时候
- 图中有入度为2的节点的时候
利用并查集来判断图中是否有环:当该条边还未加入并查集的时候,就已经有相同的根,那么该条边就是导致图中有环的边。
class Union{
public:
vector<int> parent;
vector<int> level;
Union(){
parent = vector<int>(1010, 0);
level = vector<int>(1010, 0);
}
int find(int x){
//查找当前节点的根节点
int p = x;
while(parent[p] != 0){
p = parent[p];
}
return p;
}
void merge(int x, int y){
//归并两个节点
int px = find(x);
int py = find(y);
if(level[px] > level[py]){
parent[py] = px;
}
else if(level[px] < level[py]){
parent[px] = py;
}
else{
parent[px] = py;
level[py]++;
}
}
bool same(int x, int y){
//判断两个节点是否有相同的父亲
int px = find(x);
int py = find(y);
return px == py;
}
};
class Solution {
public:
//判断能否构成一棵树
bool isTree(vector<vector<int>>& edges, int k){
Union U;
for(int i = 0; i < edges.size(); ++i){
if(i == k)
continue;
if(U.same(edges[i][0], edges[i][1])){
return false;
}
U.merge(edges[i][0], edges[i][1]);
}
return true;
}
//确定删除环中的哪一条边
vector<int> getEdges(vector<vector<int>>& edges){
Union U;
for(int i = 0; i < edges.size(); ++i){
if(U.same(edges[i][0], edges[i][1])){
return edges[i];
}
U.merge(edges[i][0], edges[i][1]);
}
return {
};
}
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
//本题利用并查集的思想
//分两种情况进行考虑
//图中有环
//图中没有环,但是有入度为2的点
//统计点的入度
int n = edges.size();
vector<int> indegree(n + 1, 0);
for(auto e : edges){
indegree[e[1]]++;
}
vector<int> vec;
for(int i = n - 1; i >= 0; --i){
if(indegree[edges[i][1]] == 2){
vec.push_back(i);
}
}
//如果有度为2的点,判断删除后是否会构成树
if(vec.size() > 0){
if(isTree(edges, vec[0])){
return edges[vec[0]];
}
else{
return edges[vec[1]];
}
}
return getEdges(edges);
}
};