P - 纳西妲的树

文章介绍了如何使用深度优先搜索(DFS)解决一个ACM编程问题,涉及计算节点之间的异或和路径,以及如何利用异或性质来找出满足特定条件的路径数量。
摘要由CSDN通过智能技术生成

https://acm.sdut.edu.cn/onlinejudge3/contests/4131/problems/P

可以先通过一次dfs去计算所有的点到节点1的路径异或和,同时记录一下1到其他点是否有符合k的数量。然后我们通过遍历每个异或和,计算他出现的次数乘他与k异或后的值出现的次数,然后把乘积都加起来就是除了根节点以外从u到v的异或和为k的数量,因为这个u,v是不分大小的,而题目分大小,因此将这个和除以2,最后再加上一开始统计的1到其他点是否有符合k的数量就是答案。

再解释一下“计算他出现的次数乘他与k异或后的值出现的次数”这种话,d数组是节点1到其他点的异或和

d[u]\bigoplus d[v] = k

d[u]\bigoplus k = d[v]

因此我们可以直接让当前值与k异或直接得到d[v] 。

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define pb push_back
using namespace std;
typedef pair<int, int>PII;
int n, m, k,cnt;
map<int, int>mp;
const int N=2e5+10;
vector<PII>g[N];
int d[N];
vector<int>a;
void dfs(int u,int fa){//求出每个点到根节点的异或和
    for(auto [v,w]:g[u]){
        if(fa==v)continue;
        d[v]=d[u]^w;
        if(d[v]==k)cnt++;//如果等于k直接加1
        if(mp[d[v]]==0)a.pb(d[v]);//记录出现过的异或和
        mp[d[v]]++;//记录出现过的异或和数量
        dfs(v,u);
    }
}
void solve () {
    cin>>n>>k;
    for(int i=1;i<n;i++){
        int u,v,w;
        cin>>u>>v>>w;
        g[u].pb({v,w});
        g[v].pb({u,w});
    }
    dfs(1,-1);
    int res=0;
    for(auto v:a){
        int c=k^v;
        if(mp[c])
        res+=mp[v]*mp[c];
    }
    cout<<res/2+cnt;
}
signed main () {
    int T = 1; 
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    //cin>>T;
    while (T --) solve ();
    return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值