[leetCode]1579. 保证图可完全遍历

题目

https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/

在这里插入图片描述

并查集

对于Alice来说当图中只有Alice的独占边和公共边时要求整个图是连通的,也就是说整个图的连通分量只有一个。
同理,对于Bob来说当图中只有Bob的独占边和公共边时也要求整个图是连通的。
题目要求删除最多的边,也就是要保留最少的边,可以通过给含有n个节点的无向图添加边来满足上面的要求。
添加边的策略是优先添加公共边,公共边处理完成后再分别处理Alice和Bob的独有边。
添加公共边或者独有边时,如果当前边的两个节点已经处在同一个连通分量中时,说明这条边是多余的,ans++。

class Solution {
    public int maxNumEdgesToRemove(int n, int[][] edges) {
        UnionFind ufa = new UnionFind(n);
        UnionFind ufb = new UnionFind(n);

        // 节点编号改为从0开始
        for (int[] edge : edges) {
            --edge[1];
            --edge[2];
        }

        int ans = 0;
        for (int[] edge : edges) {
            if (edge[0] == 3) {
               if (!ufa.union(edge[1], edge[2])) {
                   ans++;
               } else {
                   ufb.union(edge[1], edge[2]);
               }
            }
        }

        for (int[] edge : edges) {
            if (edge[0] == 1) {
                if (!ufa.union(edge[1], edge[2])) {
                    ans++;
                }
            } else if (edge[0] == 2) {
                if (!ufb.union(edge[1], edge[2])) {
                    ans++;
                }
            }
        }
        
        if (ufa.getCount() != 1 || ufb.getCount() != 1) {
            return -1;
        }
        return ans;
    }

    class UnionFind {
        private int[] parent;
        private int count;

        public UnionFind(int n) {
            parent = new int[n];
            count = n;
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        public int find(int x) {
            while (x != parent[x]) {
                parent[x] = parent[parent[x]];
                x = parent[x];
            }
            return x;
        }

        public boolean union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY) 
                return false;
            parent[rootX] = parent[rootY];
            count--;
            return true;
        }

        public int getCount() {
            return count;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值