题解 AT3913 【XOR Tree】

JK_LOVER

2020-07-22 17:06:00

题解

题意

给你一颗无根树,每条边有权值 w_i ,可以选择一条简单路径,将路径上的边权 xor 一个值。最后使所有边全部为 0 。求最小次数 。 QwQ

分析

证明

代码

#include<bits/stdc++.h>
using namespace std;
int read(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch)){ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x;
}
const int N = 1e6;
int n,sum[1<<17],val[N],num[N],S,dp[1<<17];
int main()
{
    n = read();
    for(int i = 1;i < n;i++)
    {
        int a = read()+1,b = read()+1,w = read();
        val[a] ^= w;val[b] ^= w;
    }
    for(int i = 1;i <= n;i++) num[val[i]]++;
    int ans = 0;
    for(int i = 1;i < 16;i++)
    ans += num[i]/2,S |= ((num[i]&1)<<i-1);
    for(int i = 1;i < 1<<15;i++)
    {
        for(int j = 1;j < 16;j++)
        {
            sum[i] ^= j * ((i>>(j-1))&1);
            dp[i] += (i>>(j-1))&1;
        }
        dp[i]--;
    }
    dp[0] = 0;
    for(int i = 1;i < 1<<15;i++)
    {
        if(sum[i]) continue;
        for(int j = i;j;j=(j-1)&i)
        {
            if(sum[j]) continue;
            dp[i] = min(dp[i],dp[i^j]+dp[j]);
        }
    }
    cout<<ans+dp[S]<<endl;
    return 0;
}