LeetCode刷题(每日一题) --1579. 保证图可完全遍历(并查集)

题目

Alice 和 Bob 共有一个无向图,其中包含 n 个节点和 3 种类型的边:

类型 1:只能由 Alice 遍历。
类型 2:只能由 Bob 遍历。
类型 3:Alice 和 Bob 都可以遍历。
给你一个数组 edges ,其中 edges[i] = [typei, ui, vi] 表示节点 ui 和 vi 之间存在类型为 typei 的双向边。请你在保证图仍能够被 Alice和 Bob 完全遍历的前提下,找出可以删除的最大边数。如果从任何节点开始,Alice 和 Bob 都可以到达所有其他节点,则认为图是可以完全遍历的。

返回可以删除的最大边数,如果 Alice 和 Bob 无法完全遍历图,则返回 -1 。

示例 1:

在这里插入图片描述

输入:n = 4, edges = [[3,1,2],[3,2,3],[1,1,3],[1,2,4],[1,1,2],[2,3,4]]
输出:2 解释:如果删除 [1,1,2] 和 [1,1,3] 这两条边,Alice 和 Bob
仍然可以完全遍历这个图。再删除任何其他的边都无法保证图可以完全遍历。所以可以删除的最大边数是 2 。

示例 2:

在这里插入图片描述

输入:n = 4, edges = [[3,1,2],[3,2,3],[1,1,4],[2,1,4]] 输出:0
解释:注意,删除任何一条边都会使 Alice 和 Bob 无法完全遍历这个图。

示例 3:

在这里插入图片描述

输入:n = 4, edges = [[3,2,3],[1,1,2],[2,3,4]] 输出:-1 解释:在当前图中,Alice
无法从其他节点到达节点 4 。类似地,Bob 也不能达到节点 1 。因此,图无法完全遍历。

提示:

1 <= n <= 10^5 1 <= edges.length <= min(10^5, 3 * n * (n-1) / 2)
edges[i].length == 3 1 <= edges[i][0] <= 3 1 <= edges[i][1] <
edges[i][2] <= n 所有元组 (typei, ui, vi) 互不相同

解答

思路

  • 按照题目分析,首先有三种类型,A有,B有,共有。而如果要删除最多的边,则就是留下最少的边。那么,毫无疑问,首先从公用边开始合并,(类似这种连通图的问题,默认使用并查集了)。即分别定义两个并查集容器,uf_a,uf_b,分别进行合并
  • 注意,在合并公共边时,需要两者都去调用Union函数。但是,答案自加只需要调用一次,详情看代码。
  • 在首先添加完公共边之后,依次添加单独边。如果已经连通的边,则答案自加
  • 另外还需要检查是否全部连通,因此,可以直接调用并查集类中的count变量,直接判断其是否只有一个连通量。

代码

class UF
{
public:
    vector<int> uf;
    vector<int> rank;
    vector<int> size;
    int count;
    
    UF(int n):size(n,1),uf(vector<int>(n)),rank(vector<int>(n)),count(n)
    {
        for(int i=0;i<n;++i)
        {
            uf[i]=i;
            rank[i]=i;
        }
    }

    int Find(int index)
    {
        return uf[index]==index?index:uf[index]=Find(uf[index]);
    }

    bool Union(int index1,int index2)
    {
        int find1 = Find(index1);
        int find2 = Find(index2);
        if(find1!=find2)
        {
            if(rank[find1]<rank[find2])
                swap(find1,find2);
            uf[find2] = find1;
            if(rank[find1]==rank[find2]) ++rank[find1];
            size[find1]+=size[find2];
            --count;
            return true;
        }
        return false;
    }
};

class Solution {
public:
    int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
        UF uf_a(n),uf_b(n);
        int ans=0;
        for (auto& edge: edges) 
        {
            --edge[1];
            --edge[2];
        }
        for(auto &edge:edges)
        {
            //公共边
            if(edge[0]==3)
            {
                if(!uf_a.Union(edge[1], edge[2])) ++ans;
                else uf_b.Union(edge[1],edge[2]);
            }
        }
            //单独
        for(const auto& edge: edges) 
        {
            if(edge[0]==1)
            {
                if(!uf_a.Union(edge[1],edge[2])) ++ans;
            }
            else if(edge[0]==2)
            {
                if(!uf_b.Union(edge[1],edge[2])) ++ans;
            }
        }
        if(uf_a.count!=1||uf_b.count!=1) return -1;
        return ans;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hanzoe_lwh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值