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# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using System;
using System.Linq;
using System.Collections.Generic;
using Debug = System.Diagnostics.Trace;
using SB = System.Text.StringBuilder;
using System.Numerics;
using static System.Math;
using Number = System.Int64;
namespace Program {
    public class Solver {
        Random rnd = new Random(0);
        public void Solve() {
            //全部黒の部分木はないことにしていい
            //すると葉が全て白であるような木が与えられることになる
            // u->v で移動を終えたとする。
            //このとき、全ての葉を訪れる必要がある。
            //どういうことになるかというと、dfs をして最後の帰り道の途中でやめる。
            //dfsをすることを考えるとどの頂点も次数回訪れる。
            //ただし途中で大丈夫になっていたら、その間はサボれるので次数-1回訪れる。
            //移動コストは2(N-1)
            //基本修正コスト X_u = |G[v]|+S[v]+1 mod2
            //あるパス u->v を選んだときのうれしさは パスの長さ-[u->v)パス上のX_i=0の個数+[u->v)パス上のX_i==1の個数
            var n = ri;
            var G = Enumerate(n, x => new List<int>());
            foreach (var i in Rep(n - 1)) {
                var u = ri - 1;
                var v = ri - 1;
                G[u].Add(v);
                G[v].Add(u);
            }
            var s = rs.Select(x => x == 'B' ? 1 : 0).ToArray();
            if (s.Sum() == n) { Console.WriteLine(0); return; }
            var r = Array.FindIndex(s, 0, n, x => x == 1);

            var H = Enumerate(n, x => new List<int>());
            var sz = new int[n];
            var sum = new int[n];
            Action<int, int> dfs = null;
            dfs = (prev, cur) => {
                sz[cur] = 1;
                sum[cur] = s[cur];
                foreach (var t in G[cur])
                    if (t != prev) {
                        dfs(cur, t);
                        if (sz[t] != sum[t]) {
                            sz[cur] += sz[t];
                            sum[cur] += sum[t];
                            H[cur].Add(t);
                            H[t].Add(cur);
                        }
                    }
            };
            dfs(-1, r);
            var X = new int[n];
            foreach (var i in Rep(n))
                X[i] = (1 + s[i] + H[i].Count) % 2;
            var ans = solve(X, H, r);
            Console.WriteLine(ans);
        }
        int solve(int[] c, List<int>[] G, int r) {
            //頂点が白と黒で塗られた木が与えられる
            //u--v パスを選んで取ると パスの長さ+vまでの間に訪れた白の頂点の個数-黒の頂点の個数が得点
            //基本コスト-Max(パス上の白の頂点の個数*2)が答え
            Debug.WriteLine(c.AsJoinedString());
            var add = 0;
            var ans = 0;
            Func<int, int, int> dfs = null;
            dfs = (prev, cur) => {
                add += 2;
                var ret = 0;
                if (c[cur] == 1) { ret = 1; add++; }
                foreach (var t in G[cur])
                    if (t != prev) {
                        Debug.WriteLine($"{cur + 1} {t + 1}");
                        var res = dfs(cur, t);
                        ans = Max(ans, (ret + res));
                        ret = Max(ret, res + c[cur]);
                    }
                ans = Max(ans, ret);
                return ret;
            };

            dfs(-1, r);
            add -= 2;
            Debug.WriteLine(add);
            Debug.WriteLine(ans);
            return add - 2 * ans;
        }
        const long INF = 1L << 60;
        int ri => sc.Integer();
        long rl => sc.Long();
        double rd => sc.Double();
        string rs => sc.Scan();
        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());

        static IEnumerable<int> Rep(int n) => Enumerable.Range(0, n);
        static IEnumerable<int> RRep(int n) => Enumerable.Range(0, n).Reverse();
        static T[] Enumerate<T>(int n, Func<int, T> f) {
            var a = new T[n];
            for (int i = 0; i < a.Length; ++i) a[i] = f(i);
            return a;
        }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }
    }
}
#region main
static class Ex {
    static public string AsString(this IEnumerable<char> ie) { return new string(ie.ToArray()); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") {
        return string.Join(st, ie);
    }
    static public void Main() {
        Console.SetOut(new Program.IO.Printer(Console.OpenStandardOutput()) { AutoFlush = false });
        var solver = new Program.Solver();
        solver.Solve();
        Console.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO {
    using System.IO;
    using System.Text;
    using System.Globalization;

    public class Printer : StreamWriter {
        public override IFormatProvider FormatProvider => CultureInfo.InvariantCulture;
        public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
    }

    public class StreamScanner {
        public StreamScanner(Stream stream) { str = stream; }

        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;

        private byte read() {
            if (isEof) return 0;
            if (ptr >= len) {
                ptr = 0;
                if ((len = str.Read(buf, 0, 1024)) <= 0) {
                    isEof = true;
                    return 0;
                }
            }
            return buf[ptr++];
        }

        public char Char() {
            byte b = 0;
            do b = read(); while ((b < 33 || 126 < b) && !isEof);
            return (char)b;
        }
        public string Scan() {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read()) sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine() {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n' && b != 0; b = (char)read()) if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long() { return isEof ? long.MinValue : long.Parse(Scan()); }
        public int Integer() { return isEof ? int.MinValue : int.Parse(Scan()); }
        public double Double() { return isEof ? double.NaN : double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
}

#endregion