力扣 1579. 保证图可完全遍历 并查集 贪心

https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/
力扣 1579. 保证图可完全遍历 并查集 贪心_第1张图片
思路:这题目是有点贪心的思想在里面的。考虑任意两个不同的点 ( a , b ) (a,b) (a,b),假设他们之间存在类型为 3 3 3的边,那么这两点之间的其余边都可以删去,仅保留这一条边即可,所以我们应该先把类型为 3 3 3的边连起来的点合并到一起,其余的顶点就只能通过普通边来连接了。这就启发我们用并查集来做,由于普通边有两种,所以我们需要维护两个并查集,当任意两个点已经在同一集合内时,意味着我们可以把这条边删去(类似的思想用遍历也是可以做到的,不过要比并查集麻烦一些)。注意这题还有一个坑点,虽然元组不会重复,但是每条边是双向边,所以 ( k , x , y ) (k,x,y) (k,x,y) ( k , y , x ) (k,y,x) (k,y,x)实际上也是相同的。

class ufset{
public:

    ufset(int n):elenum(n)
    {
        f.resize(n+1);
        for(int i=1;i<=n;i++)
            f[i]=i;
    }

    ufset(const ufset &u):elenum(u.elenum),f(u.f)
    {

    }

    int father(int x)
    {
        return f[x]==x?x:f[x]=father(f[x]);
    }

    bool uni(int x,int y)
    {
        int fx=father(x);
        int fy=father(y);
        if(fx==fy)
            return 1;
        f[fx]=fy;
        --elenum;
        return 0;
    }

    bool isConnected()
    {
        return elenum==1;
    }

private:
    vector<int> f;
    int elenum;
};

class Solution {
public:
    int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
        ufset s1(n);
        int ans=0;
        for(vector<int>&ele : edges)
        {
            if(ele[0]==3)
                ans+=s1.uni(ele[1],ele[2]);
        }
        ufset s2(s1);
        for(vector<int>&ele : edges)
        {
            if(ele[0]==1)
                ans+=s1.uni(ele[1],ele[2]);
            else if(ele[0]==2)
                ans+=s2.uni(ele[1],ele[2]);
        }
        if(!s1.isConnected()||!s2.isConnected())
            ans=-1;
        return ans;
    }
};

你可能感兴趣的:(力扣,并查集,贪心)