首页 > 其他分享 >可以被K整除连通块的最大数目

可以被K整除连通块的最大数目

时间:2023-10-01 14:33:30浏览次数:33  
标签:连通 vector int edge edges 整除 数目 节点

给你一棵 n 个节点的无向树,节点编号为 0 到 n - 1 。给你整数 n 和一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 有一条边
同时给你一个下标从 0 开始长度为 n 的整数数组 values ,其中 values[i] 是第 i 个节点的 值 。再给你一个整数 k
你可以从树中删除一些边,也可以一条边也不删,得到若干连通块。一个连通块的值定义为连通块中所有节点值之和。如果所有连通块的值都可以被 k 整除,那么我们说这是一个合法分割
请你返回所有合法分割中,连通块数目的最大值

一. 贪心分割

class Solution {
public:
    int maxKDivisibleComponents(int n, vector<vector<int>>& edges, vector<int>& values, int k) {
        //贪心进行分割,如果子树满足条件,子树中某个叶子节点也满足条件,那这颗子树必然可以进行再划分
        //所以可以选择贪心从叶子节点进行分割
        unordered_set<int> s[n];

        for(auto &edge:edges){
            s[edge[0]].insert(edge[1]);
            s[edge[1]].insert(edge[0]);
        }
        queue<int> q;
        for(int i=0;i<n;i++)
            if(s[i].size()==1||s[i].size()==0) q.push(i);
        int cnt = 0;
        while(!q.empty()){
            int cur = q.front(); q.pop();
            if(values[cur]%k==0) cnt++;
            for(auto next:s[cur]){//遍历领接边
                s[next].erase(cur);//删除关系
                if(s[next].size()==1)    q.push(next);
                if(values[cur]%k!=0) values[next]+=values[cur];
            }
        }
        return cnt;
    }
};

二. 树形dp

class Solution {
public:
    int maxKDivisibleComponents(int n, vector<vector<int>>& edges, vector<int>& values, int k) {
        vector<vector<int>> g(n);
        for (auto &e : edges) {
            int x = e[0], y = e[1];
            g[x].push_back(y);
            g[y].push_back(x);
        }

        int ans = 0;
        function<long long(int, int)> dfs = [&](int x, int fa) -> long long {
            long long sum = values[x];
            for (int y : g[x])
                if (y != fa)
                    sum += dfs(y, x);
            ans += sum % k == 0;
            return sum;
        };
        dfs(0, -1);
        return ans;
    }
};

标签:连通,vector,int,edge,edges,整除,数目,节点
From: https://www.cnblogs.com/929code/p/17738829.html

相关文章

  • 点双连通分量结论
    这些结论在点双大小不小于3时成立。对于点双中不同的三个点\(x,y,z\),存在以\(x,z\)为端点,经过\(y\)的简单路径对于点双中不同的两个点\(x,y\),存在经过\(x,y\)的简单环。对于点双中一个点\(x\)和一条边\(e\),存在经过\(x,e\)的简单环。对于点双中两个点\(x,y(x......
  • 花期内花的数目
    给你一个下标从0开始的二维整数数组flowers其中flowers[i]=[starti,endi]表示第i朵花的花期从starti到endi同时给你一个下标从0开始大小为n的整数数组people,people[i]是第i个人来看花的时间请你返回一个大小为n的整数数组answer,其中answer[i]是第i......
  • [LeetCode] 2251. 花期内花的数目 - 二分查找/有序数组
    Problem:2251.花期内花的数目思路看题目应该是一道比较经典的差分,本来准备拿差分数组做的,后来搂了一眼题解,发现用二分的方法更简单解题方法此题有一种很简便的方法,第i个人到达时间为people[i],所以我们不难找到在这个时间之前花期已经开始的花的数量,即v1=start<=people[i]......
  • LC2251 花期内花的数目
    方法一:差分因为是先修改后查询,很容易想到差分,但因为数据值域\([-10^9,10^9]\)过大,所以不能使用差分数组,而应用map进行存储,如代码所示:map<int,int>diff;//正常进行差分操作for(auto&f:flowers){diff[f[0]]++;diff[f[1]+1]--;}//dosomethingautoit......
  • 力扣-2798-满足目标工作时长的员工数目
    公司里共有n名员工,按从0到n-1编号。每个员工i已经在公司工作了hours[i]小时。公司要求每位员工工作至少target小时。给你一个下标从0开始、长度为n的非负整数数组hours和一个非负整数target。请你用整数表示并返回工作至少target小时的员工数。 示......
  • linux 中批量输出指定目录的磁盘占用和文件数目
     001、磁盘占用(base)[root@pc1test1]#lstest1test2test3(base)[root@pc1test1]#find$PWD-typed##查出所有目录/home/test1/home/test1/test1/home/test1/test1/test/home/test1/test2/home/test1/test3(base)[root@pc1test1]#find$PWD......
  • luogu P4819 [中山市选] 杀人游戏 题解 【强连通分量+缩点】
    目录题目链接思路分析代码题目链接P4819思路分析首先考虑这道题的连通性。容易发现这种类型的题目会容易产生环形的状态转移。假设我们知道了其中的一个点是否是黑白点,那么我们就可以知道所有点是否是黑白点。容易陷入一个误区:我们只能通过一个点知道他所相邻的最直接的点,如何......
  • 取模算术运算符-应用1-判断一个数能否被另外一个数整除
    C语言中判断一个整数能否被另外一个整数整除,可以使用取模运算符%。不能直接使用两个整数相除来进行计算,因为直接使用两个整数相除,结果只会保留整数,会舍弃掉小数部分。比如使用C语言计算11/2结果为5,但是11是不能被2整除的,计算结果舍弃掉了小数部分。因此需要使用取余运算符。示......
  • 点双/边双 连通分量
     点双 找到割点后一直退栈 http://ybt.ssoier.cn:8088/problem_show.php?pid=1521include<iostream>#include<algorithm>#include<cmath>#include<vector>#include<stack>usingnamespacestd;constintN=502;#defineintlonglon......
  • 一个数能被整除,等价于
    能被8整除,等价于后三位可以被8整除。能被2或5整除,等价于后一位可以被2或5整除。能被4整除,等价于后两位可以被4整除。能被3或9整除,等价于各位数字之和能被3或9整除。能被11整除,等价于奇数位各位数字之和减去偶数位各位数字之和的差值能被11整除。能被7或11或13整除,等价于后三......