套路,每个点的值等于所有与它相邻的边的值的亦或值
对一段路径亦或,相当于对这段路径末端的2个点亦或,所有路径变成0,也就是把所有点变成0;
所以统计所有点的值,相同就直接亦或他们之间的路径,然后消掉,不相同的,1-15最多1个,那么就状压DP一蛤
#include<bits/stdc++.h>
#define maxl 100010
#define inf 2000000001
using namespace std;
int n,ans,res;
int a[maxl],dp[maxl],cnt[16];
inline void prework()
{
for(int i=0;i<n;i++)
a[i]=0,cnt[i]=0;
int u,v,val;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&val);
a[u]^=val;a[v]^=val;
}
for(int i=0;i<n;i++)
cnt[a[i]]++;
res=0;ans=0;
for(int i=1;i<16;i++)
{
ans+=cnt[i]/2;
if(cnt[i]&1)
res^=(1<<i);
}
}
inline int dfs(int s)
{
if(s==0)
return 0;
if(dp[s])
return dp[s];
dp[s]=inf;
for(int i=1;i<16;i++)
if(s&(1<<i)){
for(int j=1;j<16;j++){
if(j!=i&&(s&(1<<j))){
int q=i^j;
if(s&(1<<q))
dp[s]=min(dp[s],dfs(s^(1<<i)^(1<<j)^(1<<q))+2);
else
dp[s]=min(dp[s],dfs(s^(1<<i)^(1<<j)^(1<<q))+1);
}
}
}
return dp[s];
}
inline void mainwork()
{
int x=dfs(res);
ans+=x;
}
inline void print()
{
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d",&n))
{
prework();
mainwork();
print();
}
return 0;
}