Problem:
Score : 800 points

Problem Statement

There is a tree with N vertices numbered 1 through N.
The i-th edge connects Vertex x_i and y_i.
Each vertex is painted white or black.
The initial color of Vertex i is represented by a letter c_i.
c_i = W represents the vertex is white; c_i = B represents the vertex is black.

A cat will walk along this tree.
More specifically, she performs one of the following in one second repeatedly:

Choose a vertex that is adjacent to the vertex where she is currently, and move to that vertex. Then, invert the color of the destination vertex.

Invert the color of the vertex where she is currently.

The cat's objective is to paint all the vertices black. She may start and end performing actions at any vertex.
At least how many seconds does it takes for the cat to achieve her objective?

Constraints

1 ≤ N ≤ 10^5

1 ≤ x_i,y_i ≤ N (1 ≤ i ≤ N-1)

The given graph is a tree.

c_i = W or c_i = B.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_{N-1} y_{N-1}
c_1c_2..c_N

Output

Print the minimum number of seconds required to achieve the objective.

Sample Input 1

5
1 2
2 3
2 4
4 5
WBBWW

Sample Output 1

5

The objective can be achieved in five seconds, for example, as follows:

Start at Vertex 1. Change the color of Vertex 1 to black.

Move to Vertex 2, then change the color of Vertex 2 to white.

Change the color of Vertex 2 to black.

Move to Vertex 4, then change the color of Vertex 4 to black.

Move to Vertex 5, then change the color of Vertex 5 to black.

Sample Input 2

6
3 1
4 5
2 6
6 1
3 4
WWBWBB

Sample Output 2

7

Sample Input 3

1
B

Sample Output 3

0

Sample Input 4

20
2 19
5 13
6 4
15 6
12 19
13 19
3 11
8 3
3 20
16 13
7 14
3 17
7 8
10 20
11 9
8 18
8 2
10 1
6 13
WBWBWBBWWWBBWWBBBBBW

Sample Output 4

21

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

// InterestingLSY
// codeforces&github: interestingLSY, qq: 2659723130
// 《幽灵公主》是真的好看！
#ifdef intLSY
#include <intlsy/stdc++.h>
#else
#include <bits/stdc++.h>
#endif
#include <bits/c++0x_warning.h>
using namespace std;
#define il inline
#define elif else if

// Type
#define ld double
#define ll long long
#define ull unsigned ll

// Vector
#define vc vector
#define Pb push_back
#define Pf push_front
#define Eb emplace_back
#define All(x) x.begin(),x.end()
#define AllRev(x) x.rbegin(),x.rend()

// Memory
#define Ms(_data) memset(_data,0,sizeof(_data))
#define Msn(_data,_num) memset(_data,_num,sizeof(_data))

// Pair
#define F first
#define S second
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>

// Loop
#define For(i,j) for( int (i) = 1 ; (i) <= (j) ; ++(i) )
#define For0(i,j) for( int (i) = 0 ; (i) < (j) ; ++(i) )
#define Forx(i,j,k) for( int (i) = (j) ; (i) <= (k) ; ++(i) )
#define Forstep(i,j,k,st) for( int (i) = (j) ; (i) <= (k) ; (i) += (st) )
#define fOR(i,j) for( int (i) = (j) ; (i) >= 1 ; --(i) )
#define fOR0(i,j) for( int (i) = (j)-1 ; (i) >= 0 ; --(i) )
#define fORx(i,j,k) for( int (i) = (k) ; (i) >= (j) ; --(i) )

// Read
struct InputReader{
	static constexpr int MAXSZ = 1048576;
	char buf[MAXSZ]; int p, ed;
	bool detectedEOF = false;
	il InputReader(){ p = MAXSZ; }
	il void Flush(){ p = 0; ed = fread(buf,1,MAXSZ,stdin); }
	il void GetChar( char &c ){
		if(p >= MAXSZ) Flush();
		if( p == ed ){ detectedEOF = true; }
		c = buf[p++];
	}
	il void ReadNum( char &c ){ GetChar(c); while( !isdigit(c) && c != '-' && !detectedEOF ) GetChar(c); }
	il void ReadAlpha( char &c ){ GetChar(c); while( !isalpha(c) && !detectedEOF ) GetChar(c); }
	il void ReadInt( int &ans ){
		ans = 0; int nega = 1;
		char c; ReadNum(c); if(detectedEOF) return;
		if( c == '-' ){
			nega = -1;
			GetChar(c);
		}
		while( isdigit(c) && !detectedEOF ){
			ans = ans*10 + c-'0';
			GetChar(c);
		}
		ans *= nega;
	}
	il void Readll( ll &ans ){
		ans = 0; int nega = 1;
		char c; ReadNum(c); if(detectedEOF) return;
		if( c == '-' ){
			nega = -1;
			GetChar(c);
		}
		while( isdigit(c) && !detectedEOF ){
			ans = ans*10 + c-'0';
			GetChar(c);
		}
		ans *= nega;
	}
	il void ReadString( string &x ){
		x.clear(); char ch; GetChar(ch);
		while( !isdigit(ch) && !isalpha(ch) && ch != '#' && ch != '.' && !detectedEOF ) GetChar(ch); if(detectedEOF) return;
		while( (isdigit(ch) || isalpha(ch) || ch == '#' || ch == '.') && !detectedEOF ){
			x += ch;
			GetChar(ch);
		}
	}
	il void ReadCString( char s[] ){
		int len = 0; char ch; GetChar(ch);
		while( !isdigit(ch) && !isalpha(ch) && ch != '#' && ch != '.' && !detectedEOF ) GetChar(ch); if(detectedEOF) return;
		while( (isdigit(ch) || isalpha(ch) || ch == '#' || ch == '.') && !detectedEOF ){
			s[len++] = ch;
			GetChar(ch);
		}
		s[len] = '\0';
	}
	il void SpecialRead( char &c ){
		GetChar(c); if(detectedEOF) return;
		while( !isdigit(c) && !isalpha(c) && c != '#' && c != '.' && c != '=' && c != 'B' && !detectedEOF ) GetChar(c);
	}
}In;
il void Read( int &x ){ In.ReadInt(x); }
il void Read( int &x, int &y ){ In.ReadInt(x); In.ReadInt(y); }
il void Read( int &x1 , int &x2 , int &x3 ){ In.ReadInt(x1); In.ReadInt(x2); In.ReadInt(x3); }
il void Read( int &x1 , int &x2 , int &x3 , int &x4 ){ In.ReadInt(x1); In.ReadInt(x2); In.ReadInt(x3); In.ReadInt(x4); }
il void Read( ll &x ){ In.Readll(x); }
il void Read( ll &x, ll &y ){ In.Readll(x); In.Readll(y); }
il void Read( ll &x1 , ll &x2 , ll &x3 ){ In.Readll(x1); In.Readll(x2); In.Readll(x3); }
il void Read( ll &x1 , ll &x2 , ll &x3 , ll &x4 ){ In.Readll(x1); In.Readll(x2); In.Readll(x3); In.Readll(x4); }
template<typename T> void Read( T a[] , int st , int ed ){ Forx(i,st,ed) Read(a[i]); }
#define iRead(k) int k; Read(k);
#define iRead2(a,b) iRead(a); iRead(b);
#define iRead3(a,b,c) iRead2(a,b); iRead(c);
#define iRead4(a,b,c,d) iRead2(a,b); iRead2(c,d);
#define lRead(k) ll k; Read(k);
#define lRead2(a,b) lRead(a); lRead(b);
#define lRead3(a,b,c) lRead2(a,b); lRead(c);
#define lRead4(a,b,c,d) lRead2(a,b); lRead2(c,d);

// File
#define Fin(a) freopen(a,"r",stdin)
#define Fout(a) freopen(a,"w",stdout)
il void FILEIO(){
	#ifdef intLSY
		Fin("in.in");
	#endif
}
il void FILEIO( string pname ){
	#ifndef intLSY
		Fin((pname+".in").c_str());
		Fout((pname+".out").c_str());
	#else
		Fin("in.in");
	#endif
}
il void FILEIO_OICONTEST( string pname ){
	Fin((pname+".in").c_str());
	#ifndef intLSY
		Fout((pname+".out").c_str());
	#endif
}
void Printtime(){
	#ifdef intLSY
		double _timeuse = clock()* 1000.0 / CLOCKS_PER_SEC;
		fprintf(stderr,"\n\nTime usage:\n%.0lf ms\n",_timeuse);
	#endif
}
void END(){ Printtime(); exit(0); }
template<typename T>void END( T mes ){ cout << mes << endl; END(); }

// Debug
#define B cerr << "BreakPoint" << endl;
#define O(x) cerr << #x << " " << (x) << endl;
#define o(x) cerr << #x << " " << (x) << "  ";
template<typename T0>
void P( T0 t0 ){
	cerr << t0 << endl;
}
template<typename T0, typename... Ts>
void P( T0 t0 , Ts... ts ){
	cerr << t0 << " ";
	P(ts...);
}
#define Msz(x) cerr << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
template<typename T>void Print( T a[] , int s , int t , char sp = ' ' , char ed = '\n' ){
	if( s > t ) return;
	for( int i = s ; i < t ; i++ )
		cout << a[i] << sp;
	cout << a[t] << ed;
	cout.flush();
}
template<typename T>void Print( T a , int s = 0 , int t = -1 , char sp = ' ' , char ed = '\n' ){
	if( t == -1 ) t = a.size()-1;
	for( int i = s ; i <= t ; i++ )
		cout << a[i] << sp;
	cout << ed;
	cout.flush();
}

// Optimize
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mymax(a,b) (a) = max((a),(b))
#define Mymin(a,b) (a) = min((a),(b))
#define MyMax(a,b) (a) = Max((a),(b))
#define MyMin(a,b) (a) = Min((a),(b))
#define INF (0x3f3f3f3f)
#define LINF ((long long)(0x3f3f3f3f3f3f3f3f))
#define Sqr(x) ((x)*(x))
#define Lowbit(a) ((a)&(-(a)))
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
constexpr int MAXN = 131072;
constexpr int LOG = 18;

int n;
vc<int> e[MAXN];
bool col[MAXN]; // col = 0: ok

int in[MAXN];
void GetDfsOrder(){
	function<void(int,int)> Dfs = [&]( int pos , int fa ){
		static int nowTime = 0;
		in[pos] = ++nowTime;
		for( auto v : e[pos] )
			if( v != fa )
				Dfs(v,pos);
	};
	Dfs(1,0);
}

int up[MAXN][LOG];
int dep[MAXN];
void LCAInit(){
	function<void(int,int)> Dfs = [&]( int pos , int fa ){
		dep[pos] = dep[fa] + 1;
		up[pos][0] = fa;
		For(i,LOG-1) up[pos][i] = up[up[pos][i-1]][i-1];
		for( auto v : e[pos] ){
			if( v == fa ) continue;
			Dfs(v,pos);
		}
	};
	Dfs(1,0);
}
int LCA( int a , int b ){
	if( dep[a] < dep[b] ) swap(a,b);
	fOR0(i,LOG){
		int v = up[a][i];
		if( dep[v] >= dep[b] )
			a = v;
	}
	if( a == b ) return a;
	fOR0(i,LOG){
		int u = up[a][i], v = up[b][i];
		if( u != v ){
			a = u;
			b = v;
		}
	}
	return up[a][0];
}
il int GetDis( int a , int b ){
	int lca = LCA(a,b);
	return dep[a] + dep[b] - 2*dep[lca];
}

vc<int> whites;
ll GetInitAnswer(){
	For(i,n) if(col[i]) whites.Eb(i);
	if( whites.empty() ) END(0);
	if( whites.size() == 1 ) END(1);
	sort(All(whites),[]( int a , int b ){
		return in[a] < in[b];
	});
	// Print(whites);

	ll initAns = 0;
	int last;

	static bool flags[MAXN];
	auto UpdatePath = [&]( int a , int b ){
		int lca = LCA(a,b);
		if( lca == b ) swap(a,b);
		if( lca == a ){
			flags[up[a][0]] ^= 1;
			flags[b] ^= 1;
		}else{
			flags[a] ^= 1;
			flags[b] ^= 1;
			col[lca] ^= 1;
		}
	};

	last = whites.back();
	for( auto u : whites ){
		col[u] ^= 1;
		UpdatePath(last,u);
		initAns += GetDis(last,u);
		last = u;
	}

	function<void(int,int)> Dfs = [&]( int pos , int fa ){
		for( auto v : e[pos] ){
			if( v == fa ) continue;
			Dfs(v,pos);
			flags[pos] ^= flags[v];
		}
		col[pos] ^= flags[pos];
	};

	Dfs(1,0);

	// Print(flags,1,n);
	// Print(col,1,n);
	For(i,n) initAns += col[i];
	return initAns;
}

bool ban[MAXN];
int newRoot;
void InitBan(){
	static queue<int> q;
	static int deg[MAXN];
	For(i,n) deg[i] = e[i].size();
	For(i,n) if( deg[i] == 1 and !col[i] ){
		q.push(i);
		ban[i] = true;
	}
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for( auto v : e[u] ){
			if( ban[v] or col[v] ) continue;
			--deg[v];
			if( deg[v] == 1 ){
				ban[v] = true;
				q.push(v);
			}
		}
	}
	// Print(ban,1,n);
	newRoot = [&](){ For(i,n) if(!ban[i]) return i; }();
}

ll FuckTheWorld(){
	ll tot = GetInitAnswer();
	// O(tot);
	static int cost[MAXN];
	For(i,n) cost[i] = col[i] ? -2 : 0;

	ll ans = LINF;
	function<int(int,int)> Dfs = [&]( int pos , int fa ){
		ll mi = 0, secMi = 0;
		for( int v : e[pos] ){
			if( ban[v] or v == fa ) continue;
			ll res = Dfs(v,pos);
			if( res <= mi ){
				secMi = mi;
				mi = res;
			}else
				Mymin(secMi,res);
		}
		Mymin(ans,mi+secMi+cost[pos]);
		return mi+cost[pos];
	};
	Dfs(newRoot,0);
	// O(ans);

	ans += tot;
	// Mymin(ans,tot);

	return ans;
}

int main(){
	FILEIO();

	Read(n);
	For(i,n-1){
		iRead2(a,b);
		e[a].Eb(b);
		e[b].Eb(a);
	}
	For(i,n){
		char c; In.ReadAlpha(c);
		col[i] = c == 'W';
	}
	// if( n <= 10 ) assert(0);

	InitBan();
	// For(i,n){
	// 	cout << i << " | ";
	// 	for( auto v : e[i] ) cout << v << " ";
	// 	cout << endl;
	// }

	GetDfsOrder();
	LCAInit();

	ll ans = FuckTheWorld();
	cout << ans << endl;

	END();
}