每日一题 21.01.27 LeetCode 1579. 保证图可完全遍历 java题解

题目

https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/
在这里插入图片描述

分析

删除最多数目的边=保留最少数目的边
1.优先添加公共边
2.添加独占边
在使用并查集进行合并的过程中,我们每遇到一次失败的合并操作(即需要合并的两个点属于同一个连通分量),那么就说明当前这条边可以被删除,将答案增加 1。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

class Solution {
    public int maxNumEdgesToRemove(int n, int[][] edges) {
        UnionFind ufa=new UnionFind(n);
        UnionFind ufb=new UnionFind(n);
        int ans=0;
        //节点下标从0开始
        for(int[] e:edges){
            e[1]--;
            e[2]--;
        }
        //类型3的边
        for(int[] e:edges){
            if(e[0]==3){
                //1.e[1],e[2]已连通 false ans++
                //2.e[1],e[2]未连通,true 
                if(!ufa.union(e[1],e[2])){
                    ans++;//可以删除
                }
                //不管是否连通,复制一份到Bob
                //1.Bob已连通,不动
                //2.Bob未联通,合并
                else{
                    ufb.union(e[1],e[2]);
                }
            }
        }
        //类型1,2
        for(int[] e:edges){
            //Alice的边
            if(e[0]==1){
                if(!ufa.union(e[1],e[2])){
                    ans++;
                }
            }
            //Bob的边
            else if(e[0]==2){
                if(!ufb.union(e[1],e[2])){
                    ans++;
                }
            }
        }
        //a和b的连通分量不为1,说明不可完全遍历
        if(ufa.setCount!=1||ufb.setCount!=1){
            return -1;
        }
        return ans;
    }
}
class UnionFind{
    public int[] parent;
    public int[] size;
    public int setCount;//连通分量
    public UnionFind(int n){
        parent=new int[n];
        size=new int[n];
        Arrays.fill(size,1);
        setCount=n;
        for(int i=0;i<n;i++){
            parent[i]=i;
        }
    }
    public int find(int index){
        if(parent[index]!=index){
            parent[index]=find(parent[index]);
        }
        return parent[index];
    }
    public boolean union(int index1,int index2){
        int a=find(index1);
        int b=find(index2);
        if(a==b){
            return false;
        }
        if(size[a]<size[b]){
            int tmp=a;
            a=b;
            b=tmp;
        }
        size[a]+=size[b];
        parent[b]=a;
        setCount--;
        return true;
    }
}

复杂度

在这里插入图片描述

结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值