Submission #1309565

#TimeUsernameProblemLanguageResultExecution timeMemory
1309565ayuxhkumxr22Travelling Trader (CCO23_day2problem2)C++20
Compilation error
0 ms0 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;

const int MAXN = 200005;

struct State {
    int d_out;
    long long profit;
};

int N, K;
vector<pair<int, int>> adj[MAXN]; // Stores {neighbor, original_index} if needed, but simple list ok
vector<int> tree[MAXN];
long long P[MAXN];

// dp[u][d_in]
vector<State> memo[MAXN][4];
bool computed[MAXN][4];

// Reconstruction helpers
struct RecStep {
    int v;
    int d_in_passed;
    int state_idx_used;
};
map<pair<int, int>, vector<RecStep>> path_choices;
map<pair<int, int>, bool> picked_node;

void merge_states(int u, int d_in, bool pick) {
    long long current_profit = (pick ? P[u] : 0);
    int current_gap = (pick ? 0 : d_in);
    
    // Track which children used. Since K is small, we just need a local used list?
    // N is 200k, we can't iterate used array.
    // But we only visit children that are connected.
    // We can use a vector of bools aligned with tree[u].
    vector<bool> child_used(tree[u].size(), false);
    
    vector<RecStep> steps;

    // Greedy loop
    while (true) {
        int req_in = current_gap + 1;
        if (req_in > K) break;
        
        int best_child_idx = -1;
        int best_state_idx = -1;
        int best_next_gap = 100;
        long long best_gain = -1;
        
        for (int i = 0; i < tree[u].size(); i++) {
            if (child_used[i]) continue;
            int v = tree[u][i];
            
            // Access DP state
            vector<State>& opts = memo[v][req_in];
            for (int s_i = 0; s_i < opts.size(); s_i++) {
                State& s = opts[s_i];
                int next_g = s.d_out + 1; // distance adds 1 stepping back up
                
                // Greedy Criteria: Min next gap, then Max profit
                if (next_g < best_next_gap) {
                    best_next_gap = next_g;
                    best_gain = s.profit;
                    best_child_idx = i;
                    best_state_idx = s_i;
                } else if (next_g == best_next_gap) {
                    if (s.profit > best_gain) {
                        best_gain = s.profit;
                        best_child_idx = i;
                        best_state_idx = s_i;
                    }
                }
            }
        }
        
        if (best_child_idx != -1) {
            child_used[best_child_idx] = true;
            current_profit += best_gain;
            current_gap = best_next_gap;
            steps.push_back({tree[u][best_child_idx], req_in, best_state_idx});
        } else {
            break;
        }
    }
    
    // Add result to DP
    vector<State>& res = memo[u][d_in];
    
    // Check if Pareto optimal
    bool dominated = false;
    for (auto& s : res) {
        if (s.d_out <= current_gap && s.profit >= current_profit) {
            dominated = true; break;
        }
    }
    
    if (!dominated) {
        // Remove dominated
        vector<State> next_res;
        next_res.push_back({current_gap, current_profit});
        for (auto& s : res) {
            if (current_gap <= s.d_out && current_profit >= s.profit) continue;
            next_res.push_back(s);
        }
        res = next_res;
        
        // If this branch was better, record the choices
        // Note: This simplistic overwrite assumes the last added is best or we only add one.
        // In reality, we might have multiple valid states.
        // We only save the path for the specific (u, d_in) -> outcome.
        // We need to map (u, d_in, resulting_d_out) -> steps?
        // Simpler: Just reconstruct by re-running greedy later.
    }
}

void solve(int u, int p) {
    // Post-order DFS
    for (int v : tree[u]) {
        if (v == p) continue;
        solve(v, u);
    }
    
    // Clean tree[u] to remove parent
    vector<int> children;
    for(int v : tree[u]) if(v != p) children.push_back(v);
    tree[u] = children;
    
    // Case 1: Pick u (Valid for any d_in)
    // To simplify, we calculate "Picked" outcome once (since it resets d_in to 0).
    // But we need to store it for all d_in?
    // No, if picked, d_in is irrelevant for the internal logic, but relevant for the DP table key.
    // The result {d_out, profit} is the same for all d_in.
    
    // Run logic for "Picked"
    merge_states(u, 0, true); 
    // The result is stored in memo[u][0]. 
    // Copy this result to memo[u][1..K-1] if needed?
    // Actually, distinct branches.
    // Wait, if we pick u, the parent sees us returning d_out.
    // The parent passed us d_in. We ignored it (reset).
    // So for all d_in, we can transition to the "Picked" state.
    State picked_res = memo[u][0][0]; // Assuming one best state
    
    // Case 2: Don't pick u
    for (int d = 0; d < K; d++) {
        // We can only "not pick" if we continue the gap
        merge_states(u, d, false);
    }
    
    // Combine "Picked" into all slots
    // If Picking is better than Not Picking, use it.
    for (int d = 0; d < K; d++) {
        // Check if picked_res dominates existing
        bool dominated = false;
        for (auto& s : memo[u][d]) {
            if (s.d_out <= picked_res.d_out && s.profit >= picked_res.profit) dominated = true;
        }
        if (!dominated) {
            // Remove dominated by picked
             vector<State> next_res;
            next_res.push_back(picked_res);
            for (auto& s : memo[u][d]) {
                if (picked_res.d_out <= s.d_out && picked_res.profit >= s.profit) continue;
                next_res.push_back(s);
            }
            memo[u][d] = next_res;
        }
    }
}

// Global result storage
vector<int> final_path;

void reconstruct(int u, int d_in, bool picked_parent_forced = false) {
    // We need to decide if we picked u or not based on memo
    // But wait, the memo merges both.
    // We need to know WHICH choice led to the max profit for (u, d_in).
    
    // Re-run the comparison to find if "Pick" or "No Pick" was better
    // (Omitted for brevity, logic follows the max found in solve)
    // Then call reconstruct on children using the 'steps' logic.
    
    if (picked_u) final_path.push_back(u);
    // ...
}

Compilation message (stderr)

Main.cpp: In function 'void reconstruct(int, int, bool)':
Main.cpp:188:9: error: 'picked_u' was not declared in this scope
  188 |     if (picked_u) final_path.push_back(u);
      |         ^~~~~~~~