Problem:
Score : 1000 points

Problem Statement

You are given a tree with N vertices. The vertices are numbered 0 through N-1, and the edges are numbered 1 through N-1.
Edge i connects Vertex x_i and y_i, and has a value a_i.
You can perform the following operation any number of times:

Choose a simple path and a non-negative integer x, then for each edge e that belongs to the path, change a_e by executing a_e ← a_e ⊕ x (⊕ denotes XOR).

Your objective is to have a_e = 0 for all edges e.
Find the minimum number of operations required to achieve it.

Constraints

2 ≤ N ≤ 10^5

0 ≤ x_i,y_i ≤ N-1

0 ≤ a_i ≤ 15

The given graph is a tree.

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1 a_1
x_2 y_2 a_2
:
x_{N-1} y_{N-1} a_{N-1}

Output

Find the minimum number of operations required to achieve the objective.

Sample Input 1

5
0 1 1
0 2 3
0 3 6
3 4 4

Sample Output 1

3

The objective can be achieved in three operations, as follows:

First, choose the path connecting Vertex 1, 2, and x = 1.

Then, choose the path connecting Vertex 2, 3, and x = 2.

Lastly, choose the path connecting Vertex 0, 4, and x = 4.

Sample Input 2

2
1 0 0

Sample Output 2

0

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

/*
  mail: mleautomaton@foxmail.com
  author: MLEAutoMaton
  This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi(){
	int f=1,sum=0;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return f*sum;
}
const int N=200010,M=20,Inf=2e9;
int n,a[N],cnt[M],ans,f[1<<M];
void chkmin(int &x,int y){x=min(x,y);}
int main(){
	n=gi();
	for(int i=1;i<n;i++){
		int u=gi()+1,v=gi()+1,w=gi();
		a[u]^=w;a[v]^=w;
	}
	int now=0;
	for(int i=1;i<=n;i++)cnt[a[i]]++;
	for(int i=1;i<=15;i++){ans+=cnt[i]/2;cnt[i]&=1;now+=cnt[i]<<(i-1);}
	memset(f,127,sizeof(f));f[now]=0;
	for(int i=(1<<15)-1;i;i--)
		if(f[i]<Inf)
			for(int j=1;j<=15;j++)
				if(i&(1<<j-1))
					for(int k=1;k<=15;k++)
						if(i&(1<<k-1) && j!=k){
							int x=j^k;
							if(i&(1<<x-1))chkmin(f[i-(1<<j-1)-(1<<k-1)-(1<<x-1)],f[i]+2);
							else chkmin(f[i-(1<<j-1)-(1<<k-1)+(1<<x-1)],f[i]+1);
						}
	printf("%d\n",f[0]+ans);
	return 0;
}