// FUCK JAVA
#include "bits/stdc++.h"
using namespace std;
struct Edge {
const int to;
const int dir;
Edge(int to, int dir)
: to(to), dir(dir) {}
};
inline int mapDirToInt(char dir) {
switch (dir) {
case 'L': return 0;
case 'R': return 1;
case 'U': return 2;
case 'D': return 3;
default: assert(false);
}
}
void solve() {
int n;
cin >> n;
vector<vector<Edge>> adj(n);
for (int i = 0; i < n - 1; ++i) {
int a, b;
char c;
cin >> a >> b >> c;
--a;
--b;
adj[a].emplace_back(b, mapDirToInt(c));
adj[b].emplace_back(a, mapDirToInt(c));
}
vector<bool> down(n, false);
vector<vector<int>> visDir(n, vector<int>(4));
auto isGoodBranch = [&](const Edge &e) {
return down[e.to] && !visDir[e.to][e.dir ^ 1];
};
auto dfsDown = [&](auto self, int node, int parent) -> void {
down[node] = true;
for (auto &edge : adj[node]) {
auto [child, dir] = edge;
if (child == parent) {
continue;
}
if (visDir[node][dir]) {
down[node] = false;
} else {
visDir[node][dir] = true;
}
self(self, child, node);
down[node] = down[node] && isGoodBranch(edge);
}
};
dfsDown(dfsDown, 0, -1);
vector<bool> up(n, false);
up[0] = true;
auto dfsUp = [&](auto self, int node, int parent) -> void {
vector<int> dirFreq(4, 0);
int cntGoodBranches = 0;
int cntChildren = 0;
for (auto &edge : adj[node]) {
auto [child, dir] = edge;
if (child != parent) {
++cntChildren;
if (isGoodBranch(edge)) {
++cntGoodBranches;
}
}
++dirFreq[dir];
}
for (auto &edge : adj[node]) {
auto [child, dir] = edge;
if (child == parent) {
continue;
}
--dirFreq[dir];
if (isGoodBranch(edge)) {
--cntGoodBranches;
}
bool hasDuplicates = false;
if (*max_element(dirFreq.begin(), dirFreq.end()) > 1) {
hasDuplicates = true;
}
up[child] = up[node] && !hasDuplicates && cntGoodBranches == cntChildren - 1 && dirFreq[dir ^ 1] == 0;
self(self, child, node);
if (isGoodBranch(edge)) {
++cntGoodBranches;
}
++dirFreq[dir];
}
};
dfsUp(dfsUp, 0, -1);
vector<bool> can(n, false);
for (int node = 0; node < n; ++node) {
vector<int> dirFreq(4, 0);
for (auto edge : adj[node]) {
++dirFreq[edge.dir];
}
can[node] = down[node] && up[node] && (*max_element(dirFreq.begin(), dirFreq.end()) <= 1);
}
for (int node = 0; node < n; ++node) {
if (can[node]) {
cout << node + 1 << ' ';
}
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
Copy