Problem:
G - Tree Happiness
Time Limit: 2 sec
問題文
$N$ 頂点の木があり、各頂点には $1$ から $N$ までの番号が振られています。また、 $i$ 番目の辺は頂点 $u_i$ と頂点 $v_i$ を双方向に結んでおり、その辺の上には英小文字 $c_i$ が書かれています。
このとき、頂点のペア $(x,y)$ （ただし $x<y$）であって次の条件を満たすものの数を求めてください。
条件： 頂点 $x$ から頂点 $y$ への最短パス（これは一意に定まります）に含まれる辺に書かれている文字を全てつなぎ合わせる。
そうして作った文字列中の文字を適切に並び替えることで、回文を作ることができる。
制約
$2 \leq N \leq 10^5$
$1 \leq u_i, v_i \leq N$
$N, u_i, v_i$ は整数
与えられるグラフは木
$c_i$ は 英小文字
入力
$N$
$u_1 \quad v_1 \quad c_1$
$u_2 \quad v_2 \quad c_2$
$\vdots$
$u_{N-1} \quad v_{N-1} \quad c_{N-1}$
出力
答えを出力してください。
入力例1
4
1
2
a
2
3
a
3
4
c
出力例1
5
頂点 $1$ から $2$ へのパス、 $1$ から $4$ へのパス上に存在する文字は、それぞれ並び替えると a, aca と回文にすることができます。
しかし、頂点 $2$ から $4$ へのパスに含まれる文字列 ac はどのように並び替えても回文になりません。
入力例2
6
1
2
a
1
3
a
1
4
a
1
5
a
1
6
a
出力例2
15

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;
using vl = vector<ll>;
using pl = pair<ll, ll>;
using vpl = vector<pair<ll, ll>>;
using vvl = vector<vl>;
using sl = set<ll>;
using spl = set<pl>;
using ml = map<ll, ll>;
using mpl = map<ll, pl>;
using mvl = map<ll, vl>;
using msl = multiset<ll>;
template<typename T> using ordered_set = tree<T, null_type,less<T>, rb_tree_tag,tree_order_statistics_node_update>;
template<typename T> using ordered_multiset = tree<T, null_type,less_equal<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define fi first
#define se second
#define vc vector
#define eb emplace_back
#define pb push_back
#define mkp make_pair
#define all(c) ((c).begin()), ((c).end())
#define F(I, S, E) for(ll I = S; I < E; I++)
#define sum(a) (accumulate((a).begin(), (a).end(), 0ll))
#define mine(a) (*min_element((a).begin(), (a).end()))
#define maxe(a) (*max_element((a).begin(), (a).end()))
#define mini(a) (min_element((a).begin(), (a).end()) - (a).begin())
#define maxi(a) (max_element((a).begin(), (a).end()) - (a).begin())
#define yes cout << "YES\n"
#define no cout << "NO\n"
#define coute cout<<"\n"

template<typename A>
istream& operator>>(istream& fin, vector<A>& v)
{
    for (auto it = v.begin(); it != v.end(); ++it)
        fin >> *it;
    return fin;
}
template<typename A, typename B>
istream& operator>>(istream& fin, pair<A, B>& p)
{
    fin >> p.fi >> p.se;
    return fin;
}

template<typename A>
ostream& operator<<(ostream& fout, vector<A>& v)
{
    for (auto it = v.begin(); it != v.end(); ++it)
        fout << *it << " ";
    fout << "\n";
    return fout;
}
template<typename A, typename B>
ostream& operator<<(ostream& fout, pair<A, B>& p)
{
    fout << p.fi << " " << p.se << "\n";
    return fout;
}

const int mod = 998244353;
const int MOD = 1e9+7;

void test_case(int test) {
    ll n;
    cin>>n;
    vc<vpl>adj(n);
    F(i,0,n-1){
        ll u,v;
        char c;
        cin>>u>>v>>c;
        u--,v--;
        // cout<<c<<" "<<c-'a'<<"\n";
        adj[u].pb({v,c-'a'});
        adj[v].pb({u,c-'a'});
    }
    // cout<<"hey\n";
    vl dp(n,-1);
    queue<ll>q;
    q.push(0);
    while(!q.empty()){
        ll u=q.front();
        q.pop();
        for(auto x:adj[u]){
            if(dp[x.fi]==-1){
                dp[x.fi]=dp[u]^(1<<x.se);
                q.push(x.fi);
            }
        }
    }
    unordered_map<ll,ll>mp;
    F(i,0,n){
        mp[dp[i]]++;
    }
    ll ans=0;
    for(auto x:mp){
        ans+=x.se*(x.se-1ll)/2;
        F(i,0,26){
            if(x.fi&(1<<i)){
                if(mp.find(x.fi^(1<<i))!=mp.end())
                ans+=x.se*mp[x.fi^(1<<i)];
            }
        }
    }
    cout<<ans<<"\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout << fixed << setprecision(20);
    int T=1;
    // cin >> T;
    for (int test = 1; test <= T; ++test) {
        test_case(test);
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 14648
final_rank: 3

code_snippet: // AOJ #3260
// // Tree Happiness 2023.2.13

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

int main(){
    int N = Cin();
    vector<vector<pair<int, char>>> adj(N+1);
    for (int i = 1; i < N; i++){
        int u = Cin(), v = Cin();
        char c = gc(); gc();
        adj[u].push_back({v, c});
        adj[v].push_back({u, c});
    }
    
    vector<int> mask(N+1, 0);
    
    vector<int> stack_node, stack_parent, stack_mask;
    stack_node.push_back(1);
    stack_parent.push_back(0);
    stack_mask.push_back(0);
    while(!stack_node.empty()){
        int node = stack_node.back(); stack_node.pop_back();
        int parent = stack_parent.back(); stack_parent.pop_back();
        int curMask = stack_mask.back(); stack_mask.pop_back();
        mask[node] = curMask;
        for (auto &edge : adj[node]){
            int nxt = edge.first;
            char letter = edge.second;
            if (nxt == parent) continue;
            int newMask = curMask ^ (1 << (letter - 'a'));
            stack_node.push_back(nxt);
            stack_parent.push_back(node);
            stack_mask.push_back(newMask);
        }
    }
    
    unordered_map<int, ll> freq;
    freq.reserve(N*2);
    for (int i = 1; i <= N; i++) freq[mask[i]]++;
    
    ll ans = 0;
    for (auto &p: freq){
        ll c = p.second;
        ans += c * (c - 1LL) / 2;
    }
    
    for (auto &p: freq){
        int m = p.first;
        ll c = p.second;
        for (int i = 0; i < 26; i++){
            int m2 = m ^ (1 << i);
            if (m2 < m) continue;
            if (freq.find(m2) != freq.end()){
                if(m2 == m) continue;
                ans += c * freq[m2];
            }
        }
    }
    Cout(ans);
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 13488
final_rank: 1

code_snippet: // AOJ #3260
// // Tree Happiness 2023.2.13

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int N;
    cin >> N;
    vector<vector<pair<int, char>>> adj(N+1);
    for (int i = 1; i <= N-1; i++){
        int u, v;
        char c;
        cin >> u >> v >> c;
        adj[u].push_back({v, c});
        adj[v].push_back({u, c});
    }
    
    vector<int> mask(N+1, 0);
    
    vector<int> stack_node, stack_parent, stack_mask;
    stack_node.push_back(1);
    stack_parent.push_back(0);
    stack_mask.push_back(0);
    while(!stack_node.empty()){
        int node = stack_node.back(); stack_node.pop_back();
        int parent = stack_parent.back(); stack_parent.pop_back();
        int curMask = stack_mask.back(); stack_mask.pop_back();
        mask[node] = curMask;
        for (auto &edge : adj[node]){
            int nxt = edge.first;
            char letter = edge.second;
            if (nxt == parent) continue;
            int newMask = curMask ^ (1 << (letter - 'a'));
            stack_node.push_back(nxt);
            stack_parent.push_back(node);
            stack_mask.push_back(newMask);
        }
    }
    
    unordered_map<int, ll> freq;
    freq.reserve(N*2);
    for (int i = 1; i <= N; i++) freq[mask[i]]++;
    
    ll ans = 0;
    for (auto &p: freq){
        ll c = p.second;
        ans += c * (c - 1LL) / 2;
    }
    
    for (auto &p: freq){
        int m = p.first;
        ll c = p.second;
        for (int i = 0; i < 26; i++){
            int m2 = m ^ (1 << i);
            if (m2 < m) continue;
            if (freq.find(m2) != freq.end()){
                if(m2 == m) continue;
                ans += c * freq[m2];
            }
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 13492
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <map>

using namespace std;
typedef long long ll;
vector<pair<int,int>> G[100010];
int d[100010];
map<ll,ll> mp;
void dfs(int s,int p){
    for(auto e:G[s]){
        if(e.first==p) continue;
        d[e.first] = d[s]^(e.second);
        dfs(e.first,s);
    }
}

int main(){
    int i,j,n; cin >> n;
    for(i=0;i<n - 1;i++){
        int u,v; cin >> u >> v; u--; v--;
        char c; cin >> c;
        int w = 1LL<<(c - 'a');
        G[u].push_back({v,w}); G[v].push_back({u,w});
    }
    d[0] = 0; dfs(0,-1);
    ll ans = 0;
    for(i=0;i<n;i++) mp[d[i]]++;
    for(i=0;i<n;i++){
        ans += mp[d[i]];
        for(j=0;j<26;j++){
            ll w = d[i]^(1LL<<j);
            if(mp.find(w)!=mp.end()) ans += mp[w];
        }
    }
    ans -= (ll)n; ans /= (ll)2;
    cout << ans << endl;
}
accuracy: 1
time_ms: 300
memory_kb: 15188
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct edge {
	int to, bit;
};

int main() {
	int N;
	cin >> N;
	vector<vector<edge> > G(N);
	for (int i = 0; i < N - 1; i++) {
		int a, b; string s;
		cin >> a >> b >> s;
		a -= 1;
		b -= 1;
		int bit = 1 << int(s[0] - 'a');
		G[a].push_back(edge{b, bit});
		G[b].push_back(edge{a, bit});
	}
	vector<int> val(N);
	auto build_tree = [&](auto& self, int pos, int pre) -> void {
		for (edge e : G[pos]) {
			if (e.to != pre) {
				val[e.to] = val[pos] ^ e.bit;
				self(self, e.to, pos);
			}
		}
	};
	build_tree(build_tree, 0, 0);
	sort(val.begin(), val.end());
	long long ans = -N;
	for (int i = 0; i < N; i++) {
		for (int j = -1; j < 26; j++) {
			int b = (j == -1 ? 0 : 1 << j);
			int pl = lower_bound(val.begin(), val.end(), (val[i] ^ b)) - val.begin();
			int pr = lower_bound(val.begin(), val.end(), (val[i] ^ b) + 1) - val.begin();
			ans += pr - pl;
		}
	}
	ans /= 2;
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 15628
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

int N;
int A[1 << 18];
int B[1 << 18];
int C[1 << 18];
int Dst[1 << 18];
vector<pair<int, int>> G[1 << 18];

void dfs(int pos, int par, int dep) {
    Dst[pos] = dep;
    for (pair<int, int> to : G[pos]) {
        if (par == to.first) continue;
        dfs(to.first, pos, dep ^ to.second);
    }
}

int main() {
    // Step 1. Input
    cin >> N;
    for (int i = 1; i <= N - 1; i++) {
        char chr;
        cin >> A[i] >> B[i] >> chr;
        C[i] = (chr - 'a');
        G[A[i]].push_back(make_pair(B[i], (1 << C[i])));
        G[B[i]].push_back(make_pair(A[i], (1 << C[i])));
    }

    // Step 2. DFS
    dfs(1, 0, 0);

    // Step 3. Get Answer
    long long Answer = 0;
    map<int, int> Map;
    for (int i = 1; i <= N; i++) {
        Answer += Map[Dst[i]];
        for (int j = 0; j < 26; j++) Answer += Map[Dst[i] ^ (1 << j)];
        Map[Dst[i]] += 1;
    }
    cout << Answer << endl;
    return 0;
}
accuracy: 1
time_ms: 940
memory_kb: 110848
final_rank: 19

code_snippet: #include <bits/stdc++.h>

using namespace std;
 
#define REP(i, n) for (ll i = 0; i < n; i++)
#define REPR(i, n) for (ll i = n; i >= 0; i--)
#define FOR(i, m, n) for (ll i = m; i < n; i++)
#define FORR(i, m, n) for (ll i = m; i >= n; i--)
#define REPO(i, n) for (ll i = 1; i <= n; i++)
#define ll long long
#define INF (ll)1 << 60
#define MINF (-1 * INF)
#define ALL(n) n.begin(), n.end()
#define MOD 1000000007
#define P pair<ll, ll>

ll n;
map<ll, ll> cnt;
ll num[110000], ans;
vector<P> g[110000];
char ch[110000];

void dfs(ll a, ll p, ll now){
    num[a] = now;
    cnt[now]++;
    for (auto& i : g[a]) {
        if(i.first == p)continue;
        dfs(i.first, a, now ^ (1 << i.second));
    }
}

int main(){
    cin >> n;
    REP(i, n - 1){
        ll a , b;
        cin >> a >> b;
        a--;
        b--;
        char c;
        cin >> c;
        g[a].push_back(P(b, c - 'a'));
        g[b].push_back(P(a, c - 'a'));
    }
    dfs(0, -1, 0);
    REP(i, n){
        REP(j, 26){
            ll v = num[i] ^ (1 << j);
            if(num[i] == v)ans += cnt[v] - 1;
            else ans += cnt[v];
        }
        ll v = num[i];
        if(num[i] == v)ans += cnt[v] - 1;
        else ans += cnt[v];
    }
    cout << ans / 2 << endl;
}
accuracy: 1
time_ms: 990
memory_kb: 136444
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 100005


struct Edge{
	Edge(int arg_to,int arg_ch){
		to = arg_to;
		ch = arg_ch;
	}
	int to,ch;
};

int N;
ll POW[30];
map<int,ll> MAP;
vector<Edge> G[SIZE];
ll table[SIZE];

void dfs(int node,int pre,int value){

	MAP[value] += 1;
	table[node] = value;

	for(int i = 0; i < G[node].size(); i++){

		int child = G[node][i].to;
		if(child == pre)continue;

		dfs(child,node,value^POW[G[node][i].ch]);
	}
}


int main(){

	POW[0] = 1;
	for(int i = 1; i < 30; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d",&N);

	int a,b,ch;
	char buf[2];

	for(int i = 0; i < N-1; i++){

		scanf("%d %d %s",&a,&b,buf);

		a--;
		b--;
		ch = buf[0]-'a';

		G[a].push_back(Edge(b,ch));
		G[b].push_back(Edge(a,ch));
	}

	dfs(0,-1,0);

	ll ans = 0;

	for(auto at = MAP.begin(); at != MAP.end(); at++){

		ans += (at->second*(at->second-1))/2;

		for(int i = 0; i < 26; i++){

			if(at->first&POW[i]){

				ans += at->second * MAP[at->first^POW[i]];
			}
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 77792
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 100005


struct Edge{
	Edge(int arg_to,int arg_ch){
		to = arg_to;
		ch = arg_ch;
	}
	int to,ch;
};

int N;
ll POW[30];
map<int,ll> MAP;
vector<Edge> G[SIZE];
ll table[SIZE];

void dfs(int node,int pre,int value){

	MAP[value] += 1;
	table[node] = value;

	for(int i = 0; i < G[node].size(); i++){

		int child = G[node][i].to;
		if(child == pre)continue;

		dfs(child,node,value^POW[G[node][i].ch]);
	}
}


int main(){

	POW[0] = 1;
	for(int i = 1; i < 30; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d",&N);

	int a,b,ch;
	char buf[2];

	for(int i = 0; i < N-1; i++){

		scanf("%d %d %s",&a,&b,buf);

		a--;
		b--;
		ch = buf[0]-'a';

		G[a].push_back(Edge(b,ch));
		G[b].push_back(Edge(a,ch));
	}

	dfs(0,-1,0);

	ll ans = 0;

	for(auto at = MAP.begin(); at != MAP.end(); at++){

		ans += (at->second*(at->second-1))/2; //自分同士

		//奇数が1個だけになるものを探す
		for(int i = 0; i < 26; i++){

			if(at->first&POW[i]){ //1つ少ない

				//printf("at->first^POW[i]:%lld\n",at->first^POW[i]);
				ans += at->second * MAP[at->first^POW[i]];
			}
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 77964
final_rank: 13

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline ll time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<vector<pair<int,int>>> g(n);
    for(int i=1;i<n;i++){
        int x,y; cin >> x >> y;
        char c; cin >> c;
        int cc = c-'a';
        x--; y--;
        g[x].push_back({y,(1<<cc)});
        g[y].push_back({x,(1<<cc)});
    }
    vector<int> d(n);
    map<int,ll> mp;
    auto dfs=[&](auto dfs,int s,int p)->void{
        mp[d[s]]++;
        for(auto t:g[s]){
            if(t.first == p)continue;
            d[t.first] = (d[s]^t.second);
            dfs(dfs,t.first,s);
        }
    };
    dfs(dfs,0,-1);
    ll res = 0;
    for(auto p:mp){
        res += p.second*(p.second-1)/2;
        for(int j=0;j<26;j++){
            int u = (p.first ^ (1<<j));
            if(p.first < u and mp.find(u) != mp.end()){
                res += p.second * mp[u];
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 21192
final_rank: 7

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>
#include <climits>
#include <map>
#include <cassert>
#include <stack>
#include <iomanip>
#include <cfloat>
#include <bitset>
#include <fstream>
#include <chrono>

int main() {
	int n; std::cin >> n;
	std::vector<std::vector<std::pair<int, int>>> graph(n);
	for (auto i = 0; i < n - 1; ++i) {
		int u, v; char c;
		std::cin >> u >> v >> c; --u; --v;
		graph[u].emplace_back(v, c - 'a');
		graph[v].emplace_back(u, c - 'a');
	}
	std::vector<int> distance(n, -1); distance[0] = 0;
	std::queue<int>  queue; queue.push(0);
	while (!queue.empty()) {
		const auto current = queue.front(); queue.pop();
		for (const auto [next, c] : graph[current]) {
			if (distance[next] >= 0) continue;
			distance[next] = distance[current] ^ (1 << c);
			queue.push(next);
		}
	}
	std::unordered_map<int, int> count;
	for (const auto d : distance) {
		count[d] += 1;
	}
	long long int result{ 0 };
	for (const auto [pattern, c]: count) {
		result += c * (c - 1LL) / 2;
		for (auto i = 0; i < 26; ++i) {
			if ((pattern >> i) & 1) continue;
			const auto other = count.find(pattern ^ (1 << i));
			if (other == count.end()) continue;
			result += other->second * (long long int) c;
		}
	}
	std::cout << result << '\n';
}
accuracy: 1
time_ms: 80
memory_kb: 12944
final_rank: 4

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>
#include <climits>
#include <map>
#include <cassert>
#include <stack>
#include <iomanip>
#include <cfloat>
#include <bitset>
#include <fstream>
#include <chrono>

int main() {
	int n; std::cin >> n;
	std::vector<std::tuple<int, int, char>> edges(n - 1);
	for (auto& [u, v, c] : edges) {
		std::cin >> u >> v >> c; --u; --v;
	}
	std::vector<std::vector<std::pair<int, int>>> graph(n);
	for (const auto [u, v, c] : edges) {
		graph[u].emplace_back(v, c - 'a');
		graph[v].emplace_back(u, c - 'a');
	}
	std::vector<int> depth(n, -1); depth[0] = 0;
	std::vector<int> history{ 0 };
	for (auto i = 0; i < history.size(); ++i) {
		const auto current = history[i];
		for (const auto [next, _] : graph[current]) {
			if (depth[next] >= 0) continue;
			depth[next] = depth[current] + 1;
			history.push_back(next);
		}
	}
	std::reverse(history.begin(), history.end());
	std::vector<std::unordered_map<int, int>> subtree(n);
	std::vector<int> base_filter(n);
	for (const auto current : history) {
		std::unordered_map<int, int> dest; dest.emplace(0, 1);
		int dest_filter{ 0 };
		for (const auto [child, c] : graph[current]) {
			if (depth[child] < depth[current]) continue;
			auto& source = subtree[child];
			auto source_filter = base_filter[child] ^ (1 << c);
			if (dest.size() < source.size()) {
				std::swap(dest, source);
				std::swap(dest_filter, source_filter);
			}
			for (const auto& [pattern, count] : source) {
				dest[pattern ^ source_filter ^ dest_filter] += count;
			}
		}
		subtree[current] = std::move(dest);
		base_filter[current] = dest_filter;
	}
	const auto root = std::move(subtree[0]);
	long long int result{ 0 };
	for (const auto& [pattern, count] : root) {
		result += (long long int)count * (count - 1) / 2;
		for (auto c = 0; c < 26; ++c) {
			if ((pattern >> c) & 1) continue;
			const auto other = root.find(pattern | (1 << c));
			if (other == root.end()) continue;
			result += (long long int)count * other->second;
		}
	}
	std::cout << result << '\n';
}
accuracy: 1
time_ms: 150
memory_kb: 39060
final_rank: 11

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(n);i++)
#define ALL(v) v.begin(),v.end()
#define debug(a) cerr<<#a<<":"<<a<<endl;
#define debug2(a,b) cerr<<"("<<#a<<","<<#b<<"):("<<a<<","<<b<<")"<<endl;
#define debug3(a,b,c) cerr<<"("<<#a<<","<<#b<<","<<#c<<"):("<<a<<","<<b<<","<<c<<")"<<endl;
#define debug4(a,b,c,d) cerr<<"("<<#a<<","<<#b<<","<<#c<<","<<d<<"):("<<a<<","<<b<<","<<c<<","<<d<<")"<<endl;

template<typename T>
istream& operator>>(istream&is,vector<T>&v){
  for(T&p:v)is>>p;
  return is;
}
template<typename T>
ostream& operator<<(ostream&os,const vector<T>&v){
  if(&os==&cerr)os<<"[";
  for(int i=0;i<v.size();i++){
    os<<v[i];
    if(i+1<v.size())os<<(&os==&cerr?",":" ");
  }
  if(&os==&cerr)os<<"]";
  return os;
}

vector<vector<pair<int,int>>> g(123456);
map<int,int> mp;
long long ans;
int now;

void dfs(int idx,int pre){
  REP(i,26)ans+=mp[now^(1<<i)];
  ans+=mp[now];
  mp[now]++;
  for(const auto&[to,c]:g[idx])if(to!=pre){
    now^=1<<c;
    dfs(to,idx);
    now^=1<<c;
  }
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n;cin>>n;
  REP(_,n-1){
    int u,v;char c;cin>>u>>v>>c;u--;v--;
    g[u].emplace_back(v,c-'a');
    g[v].emplace_back(u,c-'a');
  }
  dfs(0,-1);
  cout<<ans<<endl;
}
accuracy: 1
time_ms: 600
memory_kb: 103228
final_rank: 14

code_snippet: #include <bits/stdc++.h>
//#include<atcoder/all>
//using namespace atcoder;
using namespace std;
using ll = long long;
#define all(A) A.begin(),A.end()
using vll = vector<ll>;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
ll N;
struct ED {
	int to;
	int ch;
};

vector<vector<ED>> G;
unordered_map<int, ll> M;
ll an = 0, STR = 0;
vector<bool> seen;

int main() {
	cin >> N;
	G.resize(N);
	seen.resize(N, false);
	rep(i, N - 1) {

		int U, V;
		char C;
		cin >> U >> V >> C;
		U--, V--;
		G[U].push_back(ED{ V,C - 'a' });
		G[V].push_back(ED{ U,C - 'a' });
	}

	queue<int> Q;
	Q.push(0);
	vector<int> D(N,0);
	vll DP(N, 0);
	while (!Q.empty()) {
		ll p = Q.front();
		if (seen[p])continue;
		Q.pop();
		seen[p] = true;
		for (auto v : G[p]) {
			if (seen[v.to])continue;
			D[v.to] = D[p] ^(1 << v.ch);
			Q.push(v.to);
		}
		an +=M[D[p]];
		rep(c, 26) {
			an +=M[(D[p] ^(1 << c))];
		}
		M[D[p]]++;
	}

	cout << an << endl;
}
accuracy: 1
time_ms: 610
memory_kb: 110468
final_rank: 16

code_snippet: /*	author:  Kite_kuma
	created: 2022.03.13 13:43:56 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

struct Edge {
	int to;
	long long cost;
	Edge() = default;
	Edge(int to_, long long cost_) : to(to_), cost(cost_) {}
	bool operator<(const Edge &a) const { return cost < a.cost; }
	bool operator>(const Edge &a) const { return cost > a.cost; }
	friend std::ostream &operator<<(std::ostream &s, Edge &a) {
		s << "to: " << a.to << ", cost: " << a.cost;
		return s;
	}
};

class Graph {
	std::vector<std::vector<Edge>> edges;

   public:
	inline const std::vector<Edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<Edge> &operator[](int k) { return edges[k]; }

	int size() const { return edges.size(); }
	void resize(const int n) { edges.resize(n); }

	Graph() = default;
	Graph(int n) : edges(n) {}
	Graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const long long INF = 3e18;

	void input(int e = -1, bool weight = 0, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			long long cost = 1;
			std::cin >> u >> v;
			if(weight) std::cin >> cost;
			u -= idx, v -= idx;
			edges[u].emplace_back(v, cost);
			if(!directed) edges[v].emplace_back(u, cost);
		}
	}

	void add_edge(int u, int v, long long cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(v, cost);
		if(!directed) edges[v].emplace_back(u, cost);
	}

	// Ο(V+E)
	std::vector<long long> bfs(int s) {
		std::vector<long long> dist(size(), INF);
		std::queue<int> que;
		dist[s] = 0;
		que.push(s);
		while(!que.empty()) {
			int v = que.front();
			que.pop();
			for(auto &e : edges[v]) {
				if(dist[e.to] != INF) continue;
				dist[e.to] = dist[v] + e.cost;
				que.push(e.to);
			}
		}
		return dist;
	}

	// Ο(V+E)
	// constraint: cost of each edge is zero or one
	std::vector<long long> zero_one_bfs(int s) {
		std::vector<long long> dist(size(), INF);
		std::deque<int> deq;
		dist[s] = 0;
		deq.push_back(s);
		while(!deq.empty()) {
			int v = deq.front();
			deq.pop_front();
			for(auto &e : edges[v]) {
				assert(0LL <= e.cost and e.cost < 2LL);
				if(e.cost and dist[e.to] > dist[v] + 1) {
					dist[e.to] = dist[v] + 1;
					deq.push_back(e.to);
				} else if(!e.cost and dist[e.to] > dist[v]) {
					dist[e.to] = dist[v];
					deq.push_front(e.to);
				}
			}
		}
		return dist;
	}

	// Ο((E+V)logV)
	// cannot reach: INF
	std::vector<long long> dijkstra(int s) {  // verified
		std::vector<long long> dist(size(), INF);
		const auto compare = [](const std::pair<long long, int> &a, const std::pair<long long, int> &b) { return a.first > b.first; };
		std::priority_queue<std::pair<long long, int>, std::vector<std::pair<long long, int>>, decltype(compare)> que{compare};
		dist[s] = 0;
		que.emplace(0, s);
		while(!que.empty()) {
			std::pair<long long, int> p = que.top();
			que.pop();
			int v = p.second;
			if(dist[v] < p.first) continue;
			for(auto &e : edges[v]) {
				if(dist[e.to] > dist[v] + e.cost) {
					dist[e.to] = dist[v] + e.cost;
					que.emplace(dist[e.to], e.to);
				}
			}
		}
		return dist;
	}

	// Ο(VE)
	// cannot reach: INF
	// negative cycle: -INF
	std::vector<long long> bellman_ford(int s) {  // verified
		int n = size();
		std::vector<long long> res(n, INF);
		res[s] = 0;
		for(int loop = 0; loop < n - 1; loop++) {
			for(int v = 0; v < n; v++) {
				if(res[v] == INF) continue;
				for(auto &e : edges[v]) {
					res[e.to] = std::min(res[e.to], res[v] + e.cost);
				}
			}
		}
		std::queue<int> que;
		std::vector<int> chk(n);
		for(int v = 0; v < n; v++) {
			if(res[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(res[e.to] > res[v] + e.cost and !chk[e.to]) {
					que.push(e.to);
					chk[e.to] = 1;
				}
			}
		}
		while(!que.empty()) {
			int now = que.front();
			que.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					que.push(e.to);
				}
			}
		}
		for(int i = 0; i < n; i++)
			if(chk[i]) res[i] = -INF;
		return res;
	}

	// Ο(V^3)
	std::vector<std::vector<long long>> warshall_floyd() {	// verified
		int n = size();
		std::vector<std::vector<long long>> dist(n, std::vector<long long>(n, INF));
		for(int i = 0; i < n; i++) dist[i][i] = 0;
		for(int i = 0; i < n; i++)
			for(auto &e : edges[i]) dist[i][e.to] = std::min(dist[i][e.to], e.cost);
		for(int k = 0; k < n; k++)
			for(int i = 0; i < n; i++) {
				if(dist[i][k] == INF) continue;
				for(int j = 0; j < n; j++) {
					if(dist[k][j] == INF) continue;
					dist[i][j] = std::min(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		return dist;
	}

	// Ο(V) (using DFS)
	// if a directed cycle exists, return {}
	std::vector<int> topological_sort() {  // verified
		std::vector<int> res;
		int n = size();
		std::vector<int> used(n, 0);
		bool not_DAG = false;
		auto dfs = [&](auto self, int k) -> void {
			if(not_DAG) return;
			if(used[k]) {
				if(used[k] == 1) not_DAG = true;
				return;
			}
			used[k] = 1;
			for(auto &e : edges[k]) self(self, e.to);
			used[k] = 2;
			res.push_back(k);
		};
		for(int i = 0; i < n; i++) dfs(dfs, i);
		if(not_DAG) return std::vector<int>{};
		std::reverse(res.begin(), res.end());
		return res;
	}

	bool is_DAG() { return !topological_sort().empty(); }  // verified

	// Ο(V)
	// array of the distance from each vertex to the most distant vertex
	std::vector<long long> height() {  // verified
		auto vec1 = bfs(0);
		int v1 = -1, v2 = -1;
		long long dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v1 = i;
		vec1 = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v2 = i;
		auto vec2 = bfs(v2);
		for(int i = 0; i < int(size()); i++) {
			if(vec1[i] < vec2[i]) vec1[i] = vec2[i];
		}
		return vec1;
	}

	// O(V+E)
	// vector<(int)(0 or 1)>
	// if it is not bipartite, return {}
	std::vector<int> bipartite_grouping() {
		std::vector<int> colors(size(), -1);
		auto dfs = [&](auto self, int now, int col) -> bool {
			colors[now] = col;
			for(auto &e : edges[now]) {
				if(col == colors[e.to]) return false;
				if(colors[e.to] == -1 and !self(self, e.to, !col)) return false;
			}
			return true;
		};
		for(int i = 0; i < int(size()); i++)
			if(!colors[i] and !dfs(dfs, i, 0)) return std::vector<int>{};
		return colors;
	}

	bool is_bipartite() { return !bipartite_grouping().empty(); }

	// Ο(V+E)
	// ((v1, v2), diameter)
	std::pair<std::pair<int, int>, long long> diameter() {	// verified
		auto vec = bfs(0);
		int v1 = -1, v2 = -1;
		long long dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec[i]) dia = vec[i], v1 = i;
		vec = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec[i]) dia = vec[i], v2 = i;
		std::pair<std::pair<int, int>, long long> res = {{v1, v2}, dia};
		return res;
	}

	// Ο(ElogV)
	long long prim() {	// verified
		long long res = 0;
		std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> que;
		for(auto &e : edges[0]) que.push(e);
		std::vector<int> chk(size());
		chk[0] = 1;
		int cnt = 1;
		while(cnt < size()) {
			auto e = que.top();
			que.pop();
			if(chk[e.to]) continue;
			cnt++;
			res += e.cost;
			chk[e.to] = 1;
			for(auto &e2 : edges[e.to]) que.push(e2);
		}
		return res;
	}

	// Ο(ElogE)
	long long kruskal() {  // verified
		std::vector<std::tuple<int, int, long long>> Edges;
		for(int i = 0; i < int(size()); i++)
			for(auto &e : edges[i]) Edges.emplace_back(i, e.to, e.cost);
		std::sort(Edges.begin(), Edges.end(), [](const std::tuple<int, int, long long> &a, const std::tuple<int, int, long long> &b) {
			return std::get<2>(a) < std::get<2>(b);
		});
		std::vector<int> uf_data(size(), -1);
		auto root = [&uf_data](auto self, int x) -> int {
			if(uf_data[x] < 0) return x;
			return uf_data[x] = self(self, uf_data[x]);
		};
		auto unite = [&uf_data, &root](int u, int v) -> bool {
			u = root(root, u), v = root(root, v);
			if(u == v) return false;
			if(uf_data[u] > uf_data[v]) std::swap(u, v);
			uf_data[u] += uf_data[v];
			uf_data[v] = u;
			return true;
		};
		long long ret = 0;
		for(auto &e : Edges)
			if(unite(std::get<0>(e), std::get<1>(e))) ret += std::get<2>(e);
		return ret;
	}

	// O(V)
	std::vector<int> centroid() {
		int n = size();
		std::vector<int> centroid, sz(n);
		auto dfs = [&](auto self, int now, int per) -> void {
			sz[now] = 1;
			bool is_centroid = true;
			for(auto &e : edges[now]) {
				if(e.to != per) {
					self(self, e.to, now);
					sz[now] += sz[e.to];
					if(sz[e.to] > n / 2) is_centroid = false;
				}
			}
			if(n - sz[now] > n / 2) is_centroid = false;
			if(is_centroid) centroid.push_back(now);
		};
		dfs(dfs, 0, -1);
		return centroid;
	}

	// Ο(V+E)
	// directed graph from root to leaf
	Graph root_to_leaf(int root = 0) {
		Graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(now, e.to, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// Ο(V+E)
	// directed graph from leaf to root
	Graph leaf_to_root(int root = 0) {
		Graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(e.to, now, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// long long Chu_Liu_Edmonds(int root = 0) {}
};

#pragma endregion

ll solve(int n) {
	Graph g(n);
	rep(n - 1) {
		int a, b;
		cin >> a >> b;
		--a;
		--b;
		char c;
		cin >> c;
		g.add_edge(a, b, 1LL << (c - 'a'), false, 0);
	}

	const int root = 0;
	vll dist(n);
	auto dfs = [&n, &g, &dist](auto self, int now, int par) -> void {
		foa(e, g[now]) {
			if(e.to == par) continue;
			dist[e.to] = dist[now] ^ e.cost;
			self(self, e.to, now);
		}
		return;
	};
	dfs(dfs, root, -123);

	map<ll, ll> counter;
	ll ans = 0;
	auto contains = [&counter](ll value) -> ll {
		if(!counter.count(value)) return 0;
		return counter[value];
	};
	foa(value, dist) {
		rep(change, 26) { ans += contains(value ^ (1LL << change)); }
		ans += contains(value);
		counter[value]++;
	}
	// drop(ans);
	return ans;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << solve(n) << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 19112
final_rank: 9

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline ll time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<vector<pair<int,int>>> g(n);
    for(int i=1;i<n;i++){
        int x,y; cin >> x >> y;
        char c; cin >> c;
        int cc = c-'a';
        x--; y--;
        g[x].push_back({y,(1<<cc)});
        g[y].push_back({x,(1<<cc)});
    }
    vector<int> d(n);
    map<int,ll> mp;
    auto dfs=[&](auto dfs,int s,int p)->void{
        mp[d[s]]++;
        for(auto t:g[s]){
            if(t.first == p)continue;
            d[t.first] = (d[s]^t.second);
            dfs(dfs,t.first,s);
        }
    };
    dfs(dfs,0,-1);
    ll res = 0;
    for(auto p:mp){
        res += p.second*(p.second-1)/2;
        for(int j=0;j<26;j++){
            int u = (p.first ^ (1<<j));
            if(p.first < u and mp.find(u) != mp.end()){
                res += p.second * mp[u];
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 21092
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define drep(i,j,n) for(int i=0;i<(int)(n-1);i++)for(int j=i+1;j<(int)(n);j++)
#define trep(i,j,k,n) for(int i=0;i<(int)(n-2);i++)for(int j=i+1;j<(int)(n-1);j++)for(int k=j+1;k<(int)(n);k++)
#define codefor int test;scanf("%d",&test);while(test--)
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define yes(ans) if(ans)printf("yes\n");else printf("no\n")
#define Yes(ans) if(ans)printf("Yes\n");else printf("No\n")
#define YES(ans) if(ans)printf("YES\n");else printf("NO\n")
#define popcount(v) __builtin_popcountll(v)
#define vector2d(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define vector3d(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
#define vector4d(type,name,h,w,d,...) vector<vector<vector<vector<type>>>>name(h,vector<vector<vector<type>>>(w,vector<vector<type>>(d,vector<type>(__VA_ARGS__))))
using namespace std;
using ll = long long;
template<class T> using rpriority_queue = priority_queue<T, vector<T>, greater<T>>;
const int MOD=1000000007;
const int MOD2=998244353;
const int INF=1<<30;
const ll INF2=1LL<<60;
void scan(int& a){scanf("%d",&a);}
void scan(long long& a){scanf("%lld",&a);}
template<class T,class L>void scan(pair<T, L>& p){scan(p.first);scan(p.second);}
template<class T,class U,class V>void scan(tuple<T,U,V>& p){scan(get<0>(p));scan(get<1>(p));scan(get<2>(p));}
template<class T, size_t size> void scan(array<T, size>& a){ for(auto&& i : a) scan(i);}
template<class T> void scan(T& a){cin>>a;}
template<class T> void scan(vector<T>& vec){for(auto&& it:vec)scan(it);}
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){scan(head);in(tail...);}
void print(const int& a){printf("%d",a);}
void print(const long long& a){printf("%lld",a);}
void print(const double& a){printf("%.15lf",a);}
template<class T,class L>void print(const pair<T, L>& p){print(p.first);putchar(' ');print(p.second);}
template<class T> void print(const T& a){cout<<a;}
template<class T> void print(const vector<T>& vec){if(vec.empty())return;print(vec[0]);for(auto it=vec.begin();++it!= vec.end();){putchar(' ');print(*it);}}
void out(){putchar('\n');}
template<class T> void out(const T& t){print(t);putchar('\n');}
template <class Head, class... Tail> void out(const Head& head,const Tail&... tail){print(head);putchar(' ');out(tail...);}
template<class T> void dprint(const T& a){cerr<<a;}
template<class T> void dprint(const vector<T>& vec){if(vec.empty())return;cerr<<vec[0];for(auto it=vec.begin();++it!= vec.end();){cerr<<" "<<*it;}}
void debug(){cerr<<'\n';}
template<class T> void debug(const T& t){dprint(t);cerr<<endl;}
template <class Head, class... Tail> void debug(const Head& head, const Tail&... tail){dprint(head);cerr<<" ";debug(tail...);}
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
ll modinv(ll a, ll m) {ll b = m, u = 1, v = 0;while (b) {ll t = a / b;a -= t * b; swap(a, b);u -= t * v; swap(u, v);}u %= m;if (u < 0) u += m;return u;}
ll updivide(ll a,ll b){return (a+b-1)/b;}
int msb(ll v){return 63-__builtin_clzll(v);}
template<class T> void chmax(T &a,const T b){if(b>a)a=b;}
template<class T> void chmin(T &a,const T b){if(b<a)a=b;}

int main(){
    INT(n);
    vector<vector<pair<int,int>>> g(n);
    int u,v,s=0;
    char c;
    for(int i=0;i+1<n;i++){
        in(u,v,c);
        u--,v--;
        g[u].emplace_back(v,1<<(c-'a'));
        g[v].emplace_back(u,1<<(c-'a'));
    }
    ll ans=0;
    map<int,int> mp;
    function<void(int,int)> dfs=[&](int v,int par){
        ans+=mp[s]++;
        for(int i=0;i<26;i++)ans+=mp[s^(1<<i)];
        for(auto &&p:g[v]){
            if(p.first==par)continue;
            s^=p.second;
            dfs(p.first,v);
            s^=p.second;
        }
    };
    dfs(0,-1);
    out(ans);
}
accuracy: 1
time_ms: 610
memory_kb: 102524
final_rank: 15

code_snippet: #pragma region Macros
#include <bits/stdc++.h>
using namespace std;
template <class T> inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T> inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

struct Setup {
    Setup() {
        cin.tie(0);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    }
} __Setup;

using ll = long long;
#define OVERLOAD3(_1, _2, _3, name, ...) name
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
#define REP1(i, n) for(int i = 0; i < int(n); i++)
#define REP2(i, a, b) for(int i = (a); i < int(b); i++)
#define REP(...) OVERLOAD3(__VA_ARGS__, REP2, REP1)(__VA_ARGS__)
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) ((int)(v).size())
const int INF = 1 << 30;
const ll LLINF = 1LL << 60;
constexpr int MOD = 1000000007;
constexpr int MOD2 = 998244353;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

void Case(int i) { cout << "Case #" << i << ": "; }
int popcount(int x) { return __builtin_popcount(x); }
ll popcount(ll x) { return __builtin_popcountll(x); }
#pragma endregion Macros

int N;
vector<pair<int, char>> G[100000];
int X[100000];
unordered_map<int, int> mp;

void dfs(int u, int p) {
    // debug(u, bitset<26>(X[u]));
    mp[X[u]] += 1;
    for(auto [v, c] : G[u]) if(v != p) {
        X[v] = X[u] ^ (1 << (c - 'a'));
        dfs(v, u);
    }
}

int main() {
    cin >> N;
    REP(_, N-1) {
        int u, v;
        char c;
        cin >> u >> v >> c;
        u--, v--;
        G[u].emplace_back(v, c);
        G[v].emplace_back(u, c);
    }
    dfs(0, -1);
    ll ans = 0;
    for(auto [k, v] : mp) {
        REP(i, 26) if(mp.count(k ^ (1 << i))) ans += (ll)mp[k ^ (1 << i)] * v;
        ans += (ll)v * (v - 1);
    }
    ans /= 2;
    cout << ans << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 14668
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
template <class T> using V = vector<T>;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    V<ll> r(26);
    rep(i, 26) r[i] = 1 << i;
    int N;
    cin >> N;
    V<V<pair<int, int>>> G(N);
    rep(i, N - 1) {
        int u, v;
        char c;
        cin >> u >> v >> c;
        u--, v--;
        int a = c - 'a';
        G[u].push_back({v, a});
        G[v].push_back({u, a});
    }
    V<ll> B = {0}, C = {0};
    int cnt = 0;
    auto dfs = [&](auto f, int cur, int par) -> void {
        for (auto &nx : G[cur]) {
            if (par == nx.first) continue;
            ll b = B.back();
            B.push_back(b ^ r[nx.second]);
            C.push_back(0);
            f(f, nx.first, cur);
            ll b2 = B.back();
            B.push_back(b2 ^ r[nx.second]);
            C.push_back(1);
        }
    };
    dfs(dfs, 0, -1);
    ll ans = 0;
    int M = B.size();
    map<ll, ll> mp;
    rep(i, M) {
        if (C[i] == 1) continue;
        ans += mp[B[i]];
        rep(j, 26) { ans += mp[B[i] ^ r[j]]; }
        mp[B[i]]++;
    }
    show(B);
    show(r);
    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 136956
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
struct edge{
    int to;
    char c;
};
int main(){
    int N;
    cin >> N;
    vector<vector<edge>> G(N);
    vector<vector<int>> g(N);
    for(int i = 0; i < N - 1; i++){
        int a, b;
        char c;
        cin >> a >> b>> c;
        a--;
        b--;
        G[a].push_back({b, c});
        G[b].push_back({a, c});
    }
    int INF = 1000000000;
    vector<int> d(N, INF), num(N);
    queue<int> q;
    q.push(0);
    d[0] = 0;
    while(!q.empty()){
        int now = q.front();
        q.pop();
        for(auto [to, c] : G[now]){
            if(d[to] == INF){
                d[to] = d[now] + 1;
                num[to] = (num[now] ^ (1 << (c - 'a')));
                q.push(to);
            }
        }
    }
    vector<map<int, int>> cnt(2);
    for(int i = 0; i < N; i++){
        if(d[i] % 2 == 0) cnt[0][num[i]]++;
        else cnt[1][num[i]]++;
    }
    long long ans = 0;
    for(int i = 0; i < N; i++){
        ans += cnt[d[i] % 2][num[i]];
        for(int j = 0; j < 26; j++){
            ans += cnt[1 - (d[i] % 2)][num[i] ^ (1 << j)];
        }
    }
    ans -= N;
    cout << ans / 2 << endl;
}
accuracy: 1
time_ms: 940
memory_kb: 105508
final_rank: 18