保证图可完全遍历

题目来源:力扣(LeetCode)
题目链接:https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable
描述

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 。

思路:
对分别Alice和Bob建立最小生成树。先加入3类边中对他们都有贡献的边,随后加入1,3类中对Alice有贡献和2,3类中对Bob有贡献的边,并记入加入的边数,最后用于判断是否都能建立连通图。

class Solution {
public:

    int find_top(int *a,int x)
    {
        int top=x,j=x,t;
        while(a[top]!=top)top=a[top];
        while(j!=top)
        {
            t=a[j];
            a[j]=top;
            j=top;
        }
        return top;
    }
    int maxNumEdgesToRemove(int n, vector<vector<int>>& E) {

        int *a1,*a2;
        int u1,u2,v1,v2,ans=0,m;
        int f1=0,f2=0;
        bool *f;
        a1=new int[n+1];a2=new int[n+1];
        for(int i=1;i<=n;i++)a1[i]=a2[i]=i;
        m=E.size();
        f=new bool[m]();
        for(int i=0;i<m;i++)
        {
            if(E[i][0]==3)
            {
                u1=find_top(a1,E[i][1]),v1=find_top(a1,E[i][2]);
                u2=find_top(a2,E[i][1]),v2=find_top(a2,E[i][2]);
                if(u1!=v1&&u2!=v2)
                {
                    a1[u1]=v1;
                    a2[u2]=v2;
                    f[i]=true;
                    f1++,f2++;
                }
            }
        }
        for(int i=0;i<m;i++)
        {
            if(E[i][0]==1)
            {
                u1=find_top(a1,E[i][1]),v1=find_top(a1,E[i][2]);
                if(u1!=v1)a1[u1]=v1,f1++;
                else ans++;
            }
            else if(E[i][0]==2)
            {
                u2=find_top(a2,E[i][1]),v2=find_top(a2,E[i][2]);
                if(u2!=v2)a2[u2]=v2,f2++;
                else ans++;
                
            }
            else 
            {
                if(f[i])continue;
                u1=find_top(a1,E[i][1]),v1=find_top(a1,E[i][2]);
                u2=find_top(a2,E[i][1]),v2=find_top(a2,E[i][2]);
                if(u1!=v1)a1[u1]=v1,f1++;
                else if(u2!=v2)a2[u2]=v2,f2++;
                else ans++;
            }
        }
        //cout<<ans<<endl;
        if(f1!=n-1||f2!=n-1)ans=-1;
        //cout<<f1<<"   "<<f2<<endl;
        return ans;
    }
};

若有什么错误,欢迎指正^ _ ^ 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值