Code in c++
Criado em: 13 de julho de 2025
Criado em: 13 de julho de 2025
Below is a straightforward C++ solution that follows the minimax logic described in the photographed statement.
Because Alice may set exactly one node’s value to 0 before Bob ever moves, her optimal play is to wipe out the largest value she can find.
Bob then simply walks down the tree (or stops immediately) and chooses the node with the greatest remaining value on any root-to-leaf path.
Thus:
That reduces the game to a simple “largest / second-largest” computation that is O(N) time and O(1) extra space.
cpp#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); long long N, M, Two; if (!(cin >> N)) return 0; // no input cin >> M >> Two; // Two should be 2, but we don’t need it vector<long long> A(N); for (long long &x : A) cin >> x; // Read and discard the edge list; it is irrelevant to the final score for (long long i = 0, u, v; i < M; ++i) cin >> u >> v; // Find max1 (largest), its frequency, and max2 (second-largest) long long max1 = LLONG_MIN, max2 = LLONG_MIN; long long cntMax1 = 0; for (long long val : A) { if (val > max1) { max2 = max1; max1 = val; cntMax1 = 1; } else if (val == max1) { ++cntMax1; } else if (val > max2) { max2 = val; } } long long answer; if (cntMax1 >= 2) // Alice can’t wipe out every copy of the max answer = max1; else // unique maximum gets zeroed answer = (max2 == LLONG_MIN ? 0 : max2); cout << answer << '\n'; return 0; }
This meets the problem’s requirements in O(N) time and uses O(1) auxiliary memory.
Case 3
Input:
32
2
2
10
14
19
12
23
Output:
10
Explanation:
N-3, M-2, Two-2, A-[10,14,19], Edges-[[1,2], [2,3]] Bob will end the game in node 1.
pythonfrom PIL import Image import matplotlib.pyplot as plt img = Image.open('/mnt/data/17524086886888569450647906673485.jpg') plt.imshow(img); plt.axis('off') (-0.5, 4607.5, 3455.5, -0.5)
pythonplt.figure(figsize=(6,10)) plt.imshow(img.crop((200,120,1000,1500))); plt.axis('off') (-0.5, 799.5, 1379.5, -0.5)
pythonplt.figure(figsize=(6,10)) plt.imshow(img.crop((300,0,2000,1500))); plt.axis('off') (-0.5, 1699.5, 1499.5, -0.5)
pythonplt.figure(figsize=(6,10)) plt.imshow(img.crop((300,400,2000,2000))); plt.axis('off') (-0.5, 1699.5, 1599.5, -0.5)
pythonplt.figure(figsize=(6,10)) plt.imshow(img.crop((300,1000,2000,3000))); plt.axis('off') (-0.5, 1699.5, 1999.5, -0.5)
pythonplt.figure(figsize=(6,8)) plt.imshow(img.crop((300,250,2000,950))); plt.axis('off') (-0.5, 1699.5, 699.5, -0.5)
pythonplt.figure(figsize=(6,8)) plt.imshow(img.crop((300,600,2000,1300))); plt.axis('off') (-0.5, 1699.5, 699.5, -0.5)
pythonfrom functools import lru_cache def game_value(A, edges): n=len(A) tree=[[] for _ in range(n)] for u,v in edges: tree[u].append(v) # assume tree; root=0 # state: current node u, removed set bitmask maybe from functools import lru_cache # We'll encode removed mask as tuple bools maybe limited; but exhaustive search quickly large. # For this small chain we can brute. n_nodes=len(A) @lru_cache(None) def val(u, removed_mask): # bitmask int of length n_nodes for nodes zeroed # if node value zeroed, its value=0. # It's Alice's turn. best=10**9 # For each node i to zero next turn: consider all nodes 0..n-1 for i in range(n_nodes): if removed_mask>>i & 1: # already zeroed continue new_mask=removed_mask | (1<<i) # compute Bob's best response # Bob chooses stop or child move # compute value of node u considering removal cur_val=0 if (new_mask>>u & 1) else A[u] best_child=-1 # Bob stop best_score=cur_val # Bob move to each child for v in tree[u]: if (v==None): continue # if v is leaf: immediate value v_val=0 if (new_mask>>v & 1) else A[v] if tree[v]: # not leaf v_val = val(v, new_mask) best_score=max(best_score, v_val) # Alice chooses min score best=min(best, best_score) return best return val(0,0) # Test chain A=[10,14,19] edges=[(0,1),(1,2)] print(game_value(A, edges))
pythondef get_value_chain(vals): A=vals edges=[(i,i+1) for i in range(len(A)-1)] return game_value(A, edges) print(get_value_chain([10]))
pythonprint(get_value_chain([10,5]))
pythonprint(get_value_chain([25,5]))
pythonprint(get_value_chain([1,100]))
pythonprint(get_value_chain([50,60,70]))
pythondef game_value_tree(A, parent_edges): # edges list of (parent child) indexes n=len(A) tree=[[] for _ in range(n)] for u,v in parent_edges: tree[u].append(v) from functools import lru_cache @lru_cache(None) def val(u, mask): best=10**9 for i in range(n): if mask>>i & 1: continue newmask=mask| (1<<i) cur_val = 0 if newmask>>u &1 else A[u] best_score=cur_val for v in tree[u]: v_val = 0 if newmask>>v &1 else A[v] if tree[v]: v_val=val(v, newmask) best_score=max(best_score, v_val) best=min(best, best_score) return best return val(0,0) A=[10,20,5,8] edges=[(0,1),(0,2),(0,3)] print(game_value_tree(A,edges))
python# verify proper enumeration for star tree manually by exploring step1 choices only maybe from itertools import product def star_game(A): n=len(A) children = [[1,2,3]] # simple star best=1e9 for zero_index in range(n): # Step0 zero node newval=A.copy() newval[zero_index]=0 # Bob choose stop or move to leaf stop_val=newval[0] move_vals=[newval[v] for v in children[0]] best_score=max(stop_val,max(move_vals)) if best_score<best: best=best_score chosen_zero=zero_index print(best, chosen_zero) star_game([10,20,5,8])
pythondef second_largest(lst): if len(lst)<2: return 0 a=max(lst) b=max([x for x in lst if x!=a] or [a]) # if duplicates maybe. # If duplicates and same as max, second largest may equal same. Example [5,5] both duplicates -> second 5 as Alice zeros one of equal duplicates left behind; If all duplicates same, second largest = that same value. # We'll compute differently: Sort descending pick second. s=sorted(lst, reverse=True) return s[1] if len(s)>1 else 0 def compute_F(u, tree, A): # recursion if not tree[u]: # leaf but maybe root? But root leaf results list len1 # We'll compute as per rule lst=[A[u]] return second_largest(lst) lst=[A[u]] for v in tree[u]: lst.append(compute_F(v,tree,A) if tree[v] else A[v]) return second_largest(lst) A=[10,20,5,8] tree=[ [1,2,3], [], [], [] ] print(compute_F(0,tree,A))
pythonA=[10,14,19] tree=[ [1], [2], [] ] print(compute_F(0,tree,A))
pythonA=[10] tree=[ [] ] print(compute_F(0,tree,A))
pythonA=[10,5] tree=[[1], []] print(compute_F(0,tree,A))
pythonA=[50,60,70] tree=[[1],[2],[]] print(compute_F(0,tree,A))
pythonA=[5,10,3,8] tree=[[1,2],[ ],[3],[]] print(compute_F(0,tree,A))
pythonA=[5,10,3,8] edges=[(0,1),(0,2),(2,3)] print(game_value_tree(A,edges))
pythonA=[5,5,5] tree=[[1],[2],[]] print(compute_F(0,tree,A))
pythonprint(game_value_tree(A,[(0,1),(1,2)]))
pythondef second_max(arr): if len(arr)<2: return 0 max1,max2=-10**18,-10**18 for x in arr: if x>max1: max2=max1 max1=x elif x>max2: max2=x return max2 def compute_S(root, adj, A): n=len(A) visited=[False]*n def dfs(u, p): candidates=[A[u]] for v in adj[u]: if v==p: continue child_val= A[v] if (len(adj[v])==1 and v!=root) else dfs(v,u) candidates.append(child_val) return second_max(candidates) return dfs(root,-1) # test star A=[10,20,5,8] adj=[[1,2,3], [0],[0],[0]] print(compute_S(0,adj,A))
pythonA=[10,14,19] adj=[[1],[0,2],[1]] print(compute_S(0,adj,A))
pythonA=[10] adj=[[]] print(compute_S(0,adj,A))
pythonA=[5,10,3,8] adj=[[1,2],[0],[0,3],[2]] print(compute_S(0,adj,A))
pythonA=[5,5,5] adj=[[1],[0,2],[1]] print(compute_S(0,adj,A))
pythonA=[5,5,5] adj=[[1],[0,2],[1]] print(compute_S(0,adj,A))
I misunderstood the rules last time – Alice is allowed to set one new node to 0 every time Bob is about to move (not just once at the beginning).
With that extra power the game at a node u
works like this, assuming it is Alice’s turn and Bob is standing on u
.
Bob’s action | Score he would get |
---|---|
stop here | A[u] |
move to child v | • if v is a leaf → A[v] (game ends immediately)<br>• otherwise → value we’ll call S[v] |
(S[v]
is the optimal score Bob can secure from that child subtree when it is Alice’s turn again.)
Consequently, at every non-leaf node the value of the game is simply the second-largest number in the options table.
Let
textvalue(u → v) = A[v] if v is a leaf = S[v] otherwise
Create a list
choices = { A[u] } ∪ { value(u → v) | v is a child of u }
Then
S[u] = second_largest(choices) // if choices has only one element → 0
A true leaf has no children, so choices = {A[leaf]}
and S[leaf] = 0
.
Evaluating the tree bottom-up gives S[root]
, the final score when both play optimally.
The recurrence is O(N) because each edge is visited once and “second-largest” is computed in O(1).
cpp#include <bits/stdc++.h> using namespace std; using ll = long long; const ll NEG_INF = LLONG_MIN; struct Tree { vector<vector<int>> g; vector<ll> A; int N; Tree(int n): g(n), A(n), N(n) {} void addEdge(int u, int v) { g[u].push_back(v); g[v].push_back(u); } // returns the game value S[u] when it is Alice's turn and Bob stands on u ll solve() { return dfs(0, -1); } private: ll dfs(int u, int p) { // gather Bob's possible scores from this node ll max1 = NEG_INF, max2 = NEG_INF; // largest and 2nd-largest auto upd = [&](ll x) { if (x > max1) { max2 = max1; max1 = x; } else if (x > max2) { max2 = x; } }; upd(A[u]); // stopping here bool isLeaf = true; for (int v: g[u]) if (v != p) { isLeaf = false; ll childScore; if (g[v].size() == 1) // v is a leaf (only parent) childScore = A[v]; else // internal – recurse childScore = dfs(v, u); upd(childScore); } // If u is a (true) leaf, max2 is still NEG_INF – score is 0. return (max2 == NEG_INF ? 0 : max2); } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M, Two; if (!(cin >> N)) return 0; cin >> M >> Two; // Two is always 2 – not used Tree T(N); for (ll &x : T.A) cin >> x; // node values, 1-based in statement for (int i = 0; i < M; ++i) { int u, v; cin >> u >> v; --u; --v; // convert to 0-based T.addEdge(u, v); } cout << T.solve() << '\n'; return 0; }
N=3, A=[10,14,19]
)S[3] = 0
S[2]=14
Exactly the required output.
This single, bottom-up pass handles every tree in O(N) time and O(N) memory.