give solution in cpp D. Reachability and Tree tim...
تم الإنشاء في: ٢٣ يونيو ٢٠٢٥
تمت الإجابة باستخدام O4 Mini High بواسطة Chat01
تم الإنشاء في: ٢٣ يونيو ٢٠٢٥
تمت الإجابة باستخدام O4 Mini High بواسطة Chat01
give solution in cpp
D. Reachability and Tree
time limit per test2 seconds
memory limit per test256 megabytes
Let u and v be two distinct vertices in a directed graph. Let's call the ordered pair (u, v) good if there exists a path from vertex u to vertex v along the edges of the graph.
You are given an undirected tree with n vertices and n - 1 edges. Determine whether it is possible to assign a direction to each edge of this tree so that the number of good pairs in it is exactly n. If it is possible, print any way to direct the edges resulting in exactly n good pairs.
One possible directed version of the tree for the first test case.
Input
The first line contains one integer t (1 \le t \le 10^4) — the number of test cases.
The first line of each test case contains one integer n (2 \le n \le 2 \cdot 10^5) — the number of vertices in the tree.
The next n - 1 lines describe the edges. The i-th line contains two integers u_i and v_i (1 \le u_i, v_i \le n; u_i \neq v_i) — the vertices connected by the i-th edge.
It is guaranteed that the edges in each test case form an undirected tree and that the sum of n over all test cases does not exceed 2 \cdot 10^5.
Output
For each test case, print "NO" (case-insensitive) if it is impossible to direct all edges of the tree and obtain exactly n good pairs of vertices.
Otherwise, print "YES" (case-insensitive) and then print n - 1 pairs of integers u_i and v_i separated by spaces — the edges directed from u_i to v_i.
The edges can be printed in any order. If there are multiple answers, output any.
Example
InputCopy
4
5
1 2
2 4
1 3
3 5
5
1 2
1 3
1 4
4 5
2
2 1
4
3 1
1 2
2 4
OutputCopy
YES
1 2
3 1
3 5
4 2
YES
2 1
3 1
4 1
5 4
NO
YES
1 3
2 1
2 4
Note
The tree from the first test case and its possible directed version are shown in the legend above. In this version, there are exactly 5 good pairs of vertices: (3, 5), (3, 1), (3, 2), (1, 2), and (4, 2).
One possible directed version of the tree from the second test case is shown below:
In the presented answer, there are exactly 5 good pairs of vertices: (2, 1), (3, 1), (4, 1), (5, 4), and (5, 1).
In the third test case, there are only two directed pairs of vertices, but for any direction of the edge, only one pair will be good.
Analysis
We need to orient the edges of a tree on vertices so that the total number of good pairs
is exactly . A little thought shows
In a tree, a directed path of length 2 can only happen when a vertex has exactly one incoming edge and exactly one outgoing edge (so the two edges “chain” through ). If we tried to make that happen at a vertex of degree , its other incident edges would create additional length-2 paths and hence too many good pairs. Conversely, if the tree has a vertex of degree exactly 2, we can use that vertex as the unique “chain” node:
which creates exactly one extra good pair .
Since every path of length 2 in a bipartition alternates 0→1→0 or 1→0→1, one of those hops is always against the “0→1” rule, so you can never get two edges in the same direction. In particular there are no further length-2 directed paths in those components.
Putting that together:
The whole thing runs in per test, which is fine for .
cpp#include <bits/stdc++.h> using namespace std; using pii = pair<int,int>; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while(T--){ int n; cin >> n; vector<vector<int>> adj(n+1); vector<pii> edges(n-1); for(int i = 0; i < n-1; i++){ int u,v; cin >> u >> v; edges[i] = {u,v}; adj[u].push_back(v); adj[v].push_back(u); } // n=2 is impossible (only 1 reachable pair always) if(n == 2){ cout << "NO\n"; continue; } // find a vertex of degree exactly 2 int chainV = -1; for(int i = 1; i <= n; i++){ if(adj[i].size() == 2){ chainV = i; break; } } if(chainV == -1){ // no degree-2 vertex => can't create exactly one length-2 chain cout << "NO\n"; continue; } // we will build our answer edges here vector<pii> ans; ans.reserve(n-1); // pick the two neighbors of chainV int a = adj[chainV][0]; int b = adj[chainV][1]; // 1) orient the unique chain a -> chainV -> b ans.emplace_back(a, chainV); ans.emplace_back(chainV, b); // prepare to 2-color the two components when chainV is removed vector<int> side(n+1, -1); // in the 'a' component we color a with 0 // in the 'b' component we color b with 1 side[a] = 0; side[b] = 1; // BFS from 'a' skipping chainV { queue<int> q; q.push(a); while(!q.empty()){ int u = q.front(); q.pop(); for(int w: adj[u]){ if(w == chainV || side[w] != -1) continue; side[w] = side[u] ^ 1; q.push(w); } } } // BFS from 'b' skipping chainV { queue<int> q; q.push(b); while(!q.empty()){ int u = q.front(); q.pop(); for(int w: adj[u]){ if(w == chainV || side[w] != -1) continue; side[w] = side[u] ^ 1; q.push(w); } } } // we already handled the two chain edges; now // orient every other edge from color 0 -> color 1 auto norm = [&](int x,int y){ if(x>y) swap(x,y); return make_pair(x,y); }; auto c1 = norm(a, chainV); auto c2 = norm(b, chainV); for(auto &e: edges){ int u = e.first, v = e.second; auto nm = norm(u,v); if(nm == c1 || nm == c2) continue; // skip the two chain edges // orient from side==0 to side==1 if(side[u] == 0 && side[v] == 1){ ans.emplace_back(u,v); } else { ans.emplace_back(v,u); } } // sanity: we must have exactly n-1 oriented edges assert((int)ans.size() == n-1); cout << "YES\n"; for(auto &p: ans){ cout << p.first << " " << p.second << "\n"; } } return 0; }
Explanation of Key Steps
Why degree-2?
Only a vertex of degree 2 can host exactly one “incoming + outgoing” pair without spawning extra length-2 paths on its other edges.
Creating the single length-2 path
We pick the two edges adjacent to that degree-2 vertex , say and , and orient them . This single length-2 path contributes exactly one extra good pair beyond the from the edges.
Avoiding any other chains
Removing splits the tree into two pieces (one on ’s side, one on ’s side). In each component we 2-color the vertices (it’s a tree, hence bipartite) and then orient every edge from color 0➝color 1. This ensures that no two edges can line up in the same direction, so there are no other directed paths of length ≥2.
Overall the result is exactly good pairs, as required.
give solution in cpp
E. Tree Colorings
time limit per test4 seconds
memory limit per test256 megabytes
Consider a rooted undirected tree. Each vertex can be colored blue, green, or yellow. A coloring is called beautiful if it meets these conditions:
the root of the tree is green;
if you consider all blue and green vertices, they are reachable from each other without passing through any yellow vertices;
if you consider all yellow and green vertices, they are reachable from each other without passing through any blue vertices;
You are given an integer m. Your task is to calculate the minimum number of vertices in a tree with exactly m beautiful colorings.
Input
The first line contains a single integer (1 \le t \le 10^5) — the number of test cases.
The only line of each test case contains a single integer m (1 \le m \le 5 \cdot 10^5).
Output
For each test case, print a single integer — the minimum number of vertices in a tree with exactly m beautiful colorings. If such a tree does not exist, print -1.
Example
InputCopy
5
1
3
5
7
9
OutputCopy
1
2
3
4
3
Note
In the following notes, let g describe green color, b be blue, and y be yellow.
In the first example, consider a simple tree with just 1 vertex. This tree has exactly 1 beautiful coloring: the root is green.
In the second example, consider a simple tree with 2 vertices with a root at the 1-st vertex. There are exactly 3 beautiful colorings: [g, g], [g, b] and [g, y].
In the third example, consider a bamboo tree with 3 vertices with a root at the 1-st vertex. There are exactly 5 beautiful colorings: [g, g, g], [g, g, b], [g, g, y], [g, b, b] and [g, y, y].
In the fifth example, consider a tree with 3 vertices with a root at the 1-st vertex, and the other 2 vertices connected to it. There are exactly 9 beautiful colorings: [g, g, g], [g, g, b], [g, g, y], [g, b, g], [g, b, b], [g, b, y], [g, y, g], [g, y, b] and [g, y, y].
Below is an -precompute + –per query solution, where . We build two DP tables:
and one shows that is always odd and that these are exactly the building‐blocks of the global count.
where the are its children, so
Hence we do one final multiplicative DP over the divisors of to get the optimum split at the root.
cpp#include <bits/stdc++.h> using namespace std; using ll = long long; const int M = 500000; const int INF = 1000000000; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); // 1) Precompute divisors for all n<=M static vector<int> divs[M+1]; for(int d = 1; d <= M; d += 2){ // only odd divisors matter, but we can do all for(int x = d; x <= M; x += d){ divs[x].push_back(d); } } // 2) dpNodes[f] = min size of a subtree (excluding the global root) // whose A-value = f. We only care about odd f. static int dpNodes[M+1], D[M+1]; // D[g] = minimal sum of dpNodes[fi] over a factorization g = ∏ fi (all fi odd>1) // (i.e. best way to break g into children at an *internal* node) memset(dpNodes, 0x3f, sizeof dpNodes); memset(D, 0x3f, sizeof D); dpNodes[1] = 0; // no nodes needed to realize A=1 (empty product) D[1] = 0; // to factor 1 you pick nothing // Build up dpNodes in increasing order of f=3,5,7,...,M for(int f = 3; f <= M; f += 2){ int g = f - 2; // g = product of child A-values // compute D[g] = min_{d|g, d>1} ( dpNodes[d] + D[g/d] ) if(g > 1){ int best = INF; for(int d: divs[g]){ if(d == 1) continue; best = min(best, dpNodes[d] + D[g/d]); } D[g] = best; } // start with the “path”‐shape cost dpNodes[f] = (f - 1) / 2; // or use an internal node giving A = g+2 // cost = 1 (the internal node) + D[g] dpNodes[f] = min(dpNodes[f], 1 + D[g]); } // 3) dpRoot[m] = min #vertices in a full tree with exactly m colorings // Root must be green ⇒ m = ∏ A[v_i]. We pay 1 for the root plus // dpNodes[A[v_i]] for each child‐subtree. static int dpRoot[M+1]; for(int i = 0; i <= M; i++) dpRoot[i] = INF; dpRoot[1] = 1; // only the root, 1 beautiful coloring // fill in for odd m ≥3: for(int m = 3; m <= M; m += 2){ // one‐child decomposition: root→subtree with A=m if(dpNodes[m] < INF) dpRoot[m] = 1 + dpNodes[m]; // try splitting m = f * (m/f) for(int f: divs[m]){ if(f == 1 || f == m) continue; dpRoot[m] = min(dpRoot[m], dpRoot[m/f] + dpNodes[f]); } } // 4) answer queries int T; cin >> T; while(T--){ int m; cin >> m; if(m == 1){ cout << 1 << "\n"; } else if((m & 1) == 0){ cout << -1 << "\n"; } else { int ans = dpRoot[m]; if(ans >= INF) ans = -1; cout << ans << "\n"; } } return 0; }
Local DP for subtrees
We show that for any node whose parent is fixed green, its contribution
produces exactly all odd values . We let
dpNodes[f] = \min\{\text{#nodes of a subtree rooted at }v : A_v = f\}.One easily sees that the “path” shape gives with nodes, and any multi‐child shape gives where . Factoring into its child-contributions is itself a knapsack on multiplication, which we solve via
Global DP at the root
Since the global root must be green, the total count of beautiful colorings
factors as
where the are its immediate children. The total vertex‐count is . Hence
Finally we answer each query in , where is the divisor‐count, an acceptable total cost over all .
This runs in about to precompute and then per test.