1+ #pragma GCC optimize("Ofast")
2+ #pragma GCC optimize("unroll-loops")
3+ #include < bits/stdc++.h>
4+ using namespace std ;
5+
6+ typedef long long ll;
7+
8+ int n;
9+ int maxi;
10+ vector<int > numMaxInSubtree;
11+ vector<vector<int >> adjlist;
12+ vector<int > value, parent;
13+ void countMaxInSubtree (int u) {
14+ numMaxInSubtree[u] = (value[u] == maxi);
15+ for (auto v : adjlist[u]) {
16+ if (v == parent[u]) continue ;
17+ parent[v] = u;
18+ countMaxInSubtree (v);
19+ numMaxInSubtree[u] += numMaxInSubtree[v];
20+ }
21+ }
22+
23+ int main () {
24+ int tc;
25+ cin >> tc;
26+ while (tc--) {
27+ cin >> n;
28+ adjlist.assign (n, vector<int >());
29+ value.assign (n, 0 );
30+ numMaxInSubtree.assign (n, 0 );
31+ maxi = 0 ;
32+
33+ set<int > svs;
34+ for (int i = 0 ; i < n; i++) {
35+ cin >> value[i];
36+ maxi = max (maxi, value[i]);
37+ svs.insert (value[i]);
38+ }
39+ vector<int > uniqueVals = vector<int >(svs.begin (), svs.end ());
40+ reverse (uniqueVals.begin (), uniqueVals.end ()); // reverse to get the values in decreasing order
41+
42+ for (int i = 0 ; i < n - 1 ; i++) {
43+ int u, v;
44+ cin >> u >> v;
45+ u--;
46+ v--;
47+ adjlist[u].push_back (v);
48+ adjlist[v].push_back (u);
49+ }
50+
51+ parent.assign (n, -1 );
52+ parent[0 ] = 0 ;
53+ countMaxInSubtree (0 );
54+
55+ int totalMax = numMaxInSubtree[0 ];
56+ if (svs.size () == 1 ) {
57+ cout << 0 << endl;
58+ continue ;
59+ }
60+
61+ int secondMax = *(--(--svs.end ()));
62+
63+ vector<int > criticalPath;
64+ int u = 0 ;
65+ int prevVal = value[u];
66+ while (true ) {
67+ criticalPath.push_back (u);
68+
69+ int newu = -1 ;
70+ for (auto v : adjlist[u]) {
71+ if (v == parent[u]) {
72+ continue ;
73+ }
74+ if (numMaxInSubtree[v] == totalMax) {
75+ newu = v;
76+ }
77+ }
78+
79+ if (newu == -1 ) {
80+ break ;
81+ }
82+ u = newu;
83+ }
84+
85+ set<int > critpathSet (criticalPath.begin (), criticalPath.end ());
86+ vector<int > critNodeToIdx (n, -1 );
87+ for (int i = 0 ; i < criticalPath.size (); i++) {
88+ critNodeToIdx[criticalPath[i]] = i;
89+ }
90+
91+ map<int , vector<int >> m;
92+ for (int i = 0 ; i < n; i++) {
93+ m[value[i]].push_back (i);
94+ }
95+
96+
97+ int curEnd = criticalPath.size () - 1 ;
98+ int ans = 0 ;
99+ for (int i = 1 ; i < uniqueVals.size () && !ans; i++) { // iterate over unique values in decreasing order
100+ int val = uniqueVals[i];
101+ int newEnd = curEnd;
102+ for (auto u : m[val]) {
103+ if (critpathSet.find (u) == critpathSet.end ()) { // if we find this value not on a critical path, we can pick it
104+ ans = u + 1 ;
105+ break ;
106+ }
107+
108+ assert (critNodeToIdx[u] != -1 );
109+ if (critNodeToIdx[u] > curEnd) { // if we find a node of this value deeper than a node of a bigger value, we can pick it
110+ ans = u + 1 ;
111+ break ;
112+ }
113+
114+ newEnd = min (newEnd, critNodeToIdx[u]);
115+ }
116+
117+ curEnd = newEnd;
118+ }
119+
120+ cout << ans << endl;
121+ }
122+
123+ return 0 ;
124+ }
0 commit comments