力扣685冗余连接2

[题目](685. 冗余连接 II - 力扣(LeetCode))

多出的边分为两种情况。

1.边连向根节点,根节点的入度为1

将会形成有向环

2.边连向非根节点,其中一个非根节点的入度为2

可能会形成有向环或者没有有向环

dd69e678e86ab2875dc8e3414271131

这两种情况是互斥的。

第一种情况根节点入度为1:

问题可以退化为[冗余连接1](684. 冗余连接 - 力扣(LeetCode)),用并查集判断连通性,删去最后一条已经连通的点之间的边即可。

第二种情况:

先记录入度为2的点,判断删去其中一条边是否还构成树,不够成这条边就是答案,反之另一条边才是答案。

问题的关键在于如何判断是否构成一颗树,可以用并查集来判断,并查集可以判断一种 "类环结构"(无向环) 这种结构要么是

有向环 要么是其中一个节点的入度为 2 但是并查集不能准确判断是哪一种。

例如图中的第二种有环的情况:

[1,2],[2,3],[3,1],[4,3] 依次通过并查集合并操作,最后发现了3和1已经连通了无法构成树。

第二种无环的情况:

[1,2],[1,3],[2,3]依次并查集合并操作,最后发现进行[2,3]合并时,2和3已经连通了无法构成树。

核心代码

class Solution {
public:
    const static int N=1000+10;
int fa[N],rk[N];
void build(int n){
    for(int i=1;i<=n;i++){
        fa[i]=i;
        rk[i]=0;
    }
}
int find(int x){
    if(x!=fa[x]){
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y) return ;
    if(rk[x]<rk[y]){
        fa[x]=y;
    }else{
        fa[y]=x;
        if(rk[x]==rk[y]) rk[x]++;
    }
}
//删除一条边后是否构成树
bool check(int n,vector<vector<int>>& edges,int delEdge){
    build(n);
    for(int i=0;i<n;i++){
        if(i==delEdge) continue;
        if(find(edges[i][0])==find(edges[i][1])) return false;
        unite(edges[i][0],edges[i][1]);
    }
    return true;
}
 vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
       int n=edges.size();
       build(n);
       vector<int> inDegree(n+1,0);
       //入度
       for(int i=0;i<edges.size();i++){
        inDegree[edges[i][1]]++;
       }
       //记录入度为2的边
       vector<int> vec;
       for(int i=n-1;i>=0;i--){
        if(inDegree[edges[i][1]]==2){
            vec.push_back(i);
        }
       }
       //1:根节点入度为1 2:存在入度为2的节点
       if(vec.size()>0){
        if(check(n,edges,vec[0])){
            return edges[vec[0]];
        }else return edges[vec[1]];
       }
       // 根节点构成有向环 根节点入度为1
       build(n);
       for(int i=0;i<n;i++){
        int u=edges[i][0],v=edges[i][1];
        if(find(u)==find(v)) return edges[i];
        unite(u,v);
       }
       return {};
       }
};