zoukankan      html  css  js  c++  java
  • Codeforces Round #746 (Div. 2) C. Bakry and Partitioning

     

     


    解题思路:由树的归一性和异或的充分性,容易证明在每个点异或和不等于0的情况下,分成的连通块只能是奇数个。由于树的单链性,最终的每个连通块的异或和只能是所有点值的异或和。

    考虑到树的性质,再结合异或的性质,发现偶数个连通块都可以化归为同一个连通块,最终可以意识到,在同一棵树上,如果能够分成奇数个连通块,那么最好最简单且正确的转化方式

    一定是转化为三个连通块。或许其中的一个连通块可以分成三个值相等的小连通块,这也是可以接受的。我们只需要最终能利用异或的性质把它们分成起码三个。但是由反证法知道,如果一个连通块不能被分为奇数个值正确的小连通块,那么大连通块的值也必然不正确。换句话讲,我们最后需要的只是能凑出所有点异或和的连通块。

    而树上的连通块一定可从子树考虑分割,即DFS。

    出题思路:这个题的数据不容易做出来。事实上,在绝大部分情况下,输出的都是"NO"。话句话讲,题意本身就完全是人为的特殊情况。


    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int MAXN=2e5;
    struct Edge{
        int u,v,nxt;
    }e[MAXN*2];
    int head[MAXN],a[MAXN],cnt=0;
    
    void addEdge(int u,int v){
        e[++cnt].u=u;
        e[cnt].v=v;
        e[cnt].nxt=head[u];
        head[u]=cnt;
    }
    
    int needSum=0;//需要的^和 
    int okCnt=0;//可以分割的子树 
    int dfs(int nowX,int fa){
        int tmpSum=a[nowX];
        for(int i=head[nowX];i;i=e[i].nxt){
            int nowV=e[i].v;
            if(nowV!=fa){    
                tmpSum^=dfs(nowV,nowX);
            }
        }
        if(tmpSum==needSum){
            okCnt++;
            return 0;
        }else{
            return tmpSum;
        }
    }
    
    void init(){
        cnt=0;
        needSum=0;
        okCnt=0;
    }
    
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            init();
            int n,k;
            scanf("%d%d",&n,&k);
            
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                needSum^=a[i]; 
                head[i]=0;
            }
            
            for(int i=1;i<=n-1;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                addEdge(u,v);
                addEdge(v,u);
            }
            
            if(needSum==0){
                printf("YES
    ");
            }else{
                dfs(1,0);
                if(okCnt>=3&&k>=3){
                    printf("YES
    ");
                }else{
                    printf("NO
    ");
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    HDU Problem 1811 Rank of Tetris【拓扑排序+并查集】
    POJ Problem 2367 Genealogical tree【拓扑排序】
    HDU Problem 2647 Reward【拓扑排序】
    HDU Problem 1285 确定比赛名次【拓扑排序】
    HDU Problem HDU Today 【最短路】
    HDU Problem 3665 Seaside【最短路】
    HDU Problem 一个人的旅行 【最短路dijkstra】
    HDU Problem 1596 find the safest road【最短路dijkstra】
    Beyond Compare文本合并进行内容替换要注意什么
    用这些工具都可以比较代码的差异
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/15433254.html
Copyright © 2011-2022 走看看