力扣(leetcode)#1579 保证图可完全遍历(#4)

题目

原题链接:力扣(LeetCode)#1579

解析

还是并查集。。说实话,要做吐了。
本人的思想是维护两个连通集合Alice和Bob,一人一个。
关键点在于要进行两轮循环,首先判断公共边,如果公共边多了,就增加可以减去的边数。
第二轮循环进行独有边的判断。
考虑一下,两个顶点之间存在三种类型的边,并且该边不能全部省略,那么减去Alice和Bob两条独占边显然是最合算的。

代码

class Solution {
private:
    int cnt1,cnt2,rest1,rest2;
    int *a;//Alice
    int *b;//Bob 
public:
    int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
        int num=edges.size();
        cnt1=cnt2=n;
        int rest=0;
        rest1=rest2=0;
        int ans=0;
        a=new int[cnt1+1];
        b=new int[cnt2+1];
        init(n);
        for(int i=0;i<num;i++)
        {
            if(edges[i][0]==3)
            {
                merge(edges[i][1],edges[i][2],a,cnt1,rest);
                merge(edges[i][1],edges[i][2],b,cnt2,rest);
            }
            
        }
        for(int i=0;i<num;i++)
        {
            if(edges[i][0]==1)
            {
                merge(edges[i][1],edges[i][2],a,cnt1,rest1);
            }
            else if(edges[i][0]==2)
            {
                merge(edges[i][1],edges[i][2],b,cnt2,rest2);
            }
        }
        if(cnt1==1&&cnt2==1)
        {
            return rest/2+rest1+rest2;//rest除以2的原因是公共边被加了两次,翻倍了
        }
        else
            return -1;
    }

    void init(int n)
    {
        for(int i=1;i<=n;i++)
        {
            a[i]=i;
            b[i]=i;
        }
    }

    int find(int x,int* s)
    {
        if(s[x]==x)
            return x;
        else
            return s[x]=find(s[x],s);
    }

    void merge(int x, int y,int* s,int& m,int& t)
    {
        int a1=find(x,s);
        int a2=find(y,s);
        if(a1!=a2)
        {
            s[a1]=a2;
            m--;
        }
        else
        {
            t++;
        }
    }
};

结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值