栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

1592 C. Bakry and Partitioning

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

1592 C. Bakry and Partitioning

题意

有一颗树,问你能不能分成至少2个至多k个连通分量,并且每个连通分量的异或值都相同。

解析

设每个点的异或之和为xo

  1. 根据异或的性质,如果xo为0,那么说明可以分成两个区间,其两个区间的异或之和一定为0。
  2. 如果xo不为0,我们要分成m个区间,每个区间为xo,如果我们能分成10个区间,那么一定能分成8个区间,因为我们可以选择相邻的三个连通分量构成一个大连通分量,其异或值还是为xo,因此,我们最后分成的奇数个连通分量的最小值是3。
  3. 现在题目转化成,能不能分成3个连通分量,异或值相同。
  4. 思路很简单,dfs遍历每个点的所有子树,如果其自身和子树的异或之和为xo,那么就断链并且记录个数cnt++,断链的方式就是给父节点返回0。
  5. 如果最后cnt>=3 && k>=3 那么表示满足题意。
代码
#include
typedef long long ll;
using namespace std;
const int N=1e5+5;
vectorg[N];
int r[N];
int xo=0,cnt=0;
void init(int n){
    xo=0;
    cnt=0;
    for(int i=0;i<=n;i++){
        g[i].clear();
    }
}
int dfs(int x,int pre){
    int son=r[x];
    for(int j:g[x]){
        if(pre!=j){
            son^=dfs(j,x);
        }
    }
    if(son==xo){
        son=0;
        cnt++;
    }
    return son;
}

void solve(){
    int n,m;
    scanf("%d%d",&n,&m);
    init(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&r[i]);
        xo=xo^r[i];
    }
    for(int i=1;i=3 && m>=3) || xo==0){
        puts("YES");
    }
    else{
        puts("NO");
    }
}
int main() {
    int t ;
    scanf("%d",&t);
    while(t--){
        solve();
    }
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/290995.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号