Leetcode 685. 冗余连接 II(拓扑排序+并查集)

[Leetcode 685. 冗余连接 II]

思路:

\qquad 根据题意,题目中的有向图为一棵树加上一条冗余边。一棵树的所有子节点入度均为1,根节点入度为0,因此可以分为以下两种情况:
\qquad (1)图中存在入度为2的节点。因为根节点的入度为0,添加一条边,入度最多加1,因此入度为2的点一定是子节点,要删除的边一定是连向这个节点的边之一,根是入度为0的节点。此时考虑删掉每条连向该节点的边,对剩下的图从根节点拓扑排序,若没有环且能遍历到所有点,则枚举的边就是答案;
\qquad (2)图中点的入度均为1,即从子节点向根节点连一条边。此时按照边的顺序,遍历所有边,每次将一条边连接的两点合并到一个联通块。当遇到一条边的两点属于同一个联通块时,即为答案。

代码:

class Solution {
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        for(int i = 0;i < 1005; ++i) p[i] = i, in[i] = 0;
        vector<int> ans;
        ans.push_back(0), ans.push_back(0);
        int pos_0 = 0;
        int pos_2 = 0;
        for(int i = 0;i < edges.size(); ++i)
        {
            int u = edges[i][0];
            int v = edges[i][1];
            in[v]++;
            E[u].push_back(v);
            if(in[v] == 2) pos_2 = v;
        }
        for(int i = 1;i <= edges.size(); ++i) if(in[i] == 0) pos_0 = i;
        if(in[pos_2] == 2)
        {
            for(int i = 0;i < edges.size(); ++i)
            {
                int u = edges[i][0];
                int v = edges[i][1];
                if(v == pos_2)
                {
                    del_u = u;
                    del_v = v;
                    sum = 1;
                    memset(r, false, sizeof(r));
                    r[pos_0] = true;
                    if(topology(pos_0) && sum == edges.size())
                    {
                        ans[0] = u;
                        ans[1] = v;
                    }
                }
            }
        }
        else
        {
            for(int i = 0;i < edges.size(); ++i)
            {
                int u = edges[i][0];
                int v = edges[i][1];
                int u_p = find(u);
                int v_p = find(v);
                if(u_p < v_p) p[v] = u_p;
                else if(u_p > v_p) p[u] = v_p;
                else
                {
                    ans[0] = u;
                    ans[1] = v;
                    break;
                }
            }
        }
        return ans;
    }
    int p[1005];
    int in[1005];
    bool r[1005];
    int del_u;
    int del_v;
    int sum = 1;
    vector<int> E[1005];
    int find(int x)
    {
        return x == p[x] ? x : p[x] = find(p[x]);
    }
    bool topology(int u)
    {
        for(int i = 0;i < E[u].size(); ++i)
        {
            int v = E[u][i];
            if(u == del_u && v == del_v) continue;
            if(r[v]) return false;
            ++sum;
            r[v] = true;
            topology(v);
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值