Contest1800 - 2019年第二阶段我要变强个人训练赛第十七场 czr 太弱啦

UPC题解
题目描述
czr太弱啦!他现在小学组题目都不会做,于是来求助你。
问题是:给定一棵树,问路径的异或和等于k的有几条?
形式化描述:给定一棵N个节点组成的有边权的无根树,你需要计数这样的正整数对(u,v)(1≤u≤v≤n),满足若从u到v经过的路径上的边权依次为w1,w2,…,wL,那么w1 xor w2 xor…xor wL =k。其中“xor”表示非负整数按位取异或。

输入
第1行:两个正整数n,k,含义见题面描述。
第2∼n行:每一行包含三个正整数u,v,w,代表节点u、v之间存在一条权值为w的边。节点从1开始编号。

输出
第1行:一个正整数——所有路径中异或和为k的路径条数。

sample input

5 0
4 3 7
5 1 4
3 2 7
5 4 7

sample output
2

提示
有2–3–4、3–4–5共2条路径上的边权异或和为k=0。
对于所有测试数据,所有权值w满足0≤w≤231−1。
题目大意:
题目给出一些无向边,这些边上还有一定的边权,这样就构成了一个无根树,问这样的一棵树有多少条边权的异或和是K

分析:UPC里面给出的题解然后再去结合一下代码就应该差不多就可以理解了,在这里我只谈一下自己对这道题目的看法:
首先UPC中给出了下面这个式子:

x xor z xor y xor z=k

这就感觉是一种类似取模的运算模式,大家看一下,按照题目中给出的样例 1<----(4)----> 5 <----(7)----> 4 <----(7)----> 3 <----(7)----> 2
差不多就是这样样子了,然后再去模拟一下下面的代码

inline  void dfs(int now,int pre,int val){//now是当前的点,pre是前驱节点
    ans+=ma[val^k];
    ma[val]++;
    for(int i=head[now];i!=-1;i=num[i].from){
        if(num[i].to==pre) continue;
        dfs(num[i].to,now,num[i].val^val);
    }
}

就可以发现一直去异或好像是存在一个循环,异或还有一些特点就是0异或任何数还是原来的数;两个相同的数异或结果是0;
依据这个特点再去结合代码就可以得到方法了
这题和https://blog.csdn.net/c___c18/article/details/97561689有点类似的思想,但是还有很大的不同的

其实这样去写DFS也是可以的

void dfs(int now,int pre,int val){
    ans+=ma[val];//其实这两句话都是一个意思,为什么这样说呢,因为
    //  由val^k = p可知,val^p=k ,那么答案不就是p的个数吗,当然,
    //val的值不同,p也就不同,因此需要这样去做
    ma[val^k]++;
    for(int i=head[now];i!=-1;i=num[i].from){
        if(num[i].to==pre) continue;
        dfs(num[i].to,now,num[i].val^val);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值