Submission #1084574

#TimeUsernameProblemLanguageResultExecution timeMemory
1084574avighnaFirefighting (NOI20_firefighting)C++17
36 / 100
217 ms42940 KiB
#include <bits/stdc++.h>

typedef long long ll;

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);

  ll n, k;
  std::cin >> n >> k;
  std::vector<std::vector<std::pair<ll, ll>>> adj(n + 1);
  ll min_w = 1e15;
  for (ll i = 0, u, v, w; i < n - 1; ++i) {
    std::cin >> u >> v >> w;
    adj[u].push_back({v, w});
    adj[v].push_back({u, w});
    min_w = std::min(min_w, w);
  }

  if (k < min_w) {
    std::cout << n << '\n';
    for (ll i = 1; i <= n; ++i) {
      std::cout << i << ' ';
    }
    std::cout << '\n';
    return 0;
  }

  if (n <= 17) {
    std::pair<ll, ll> ans = {1e15, -1};
    for (ll mask = 1; mask < (1 << n); ++mask) {
      std::priority_queue<std::pair<ll, ll>> pq;
      std::vector<bool> vis(n + 1);
      std::vector<ll> dist(n + 1, 1e15);
      dist[0] = 0;
      for (ll i = 0; i < n; ++i) {
        if (mask & (1 << i)) {
          dist[i + 1] = 0;
          pq.push({0, i + 1});
        }
      }
      while (!pq.empty()) {
        auto [d, node] = pq.top();
        pq.pop();
        if (vis[node]) {
          continue;
        }
        vis[node] = true;
        d *= -1;
        for (auto &[ch, w] : adj[node]) {
          if (d + w < dist[ch]) {
            dist[ch] = d + w;
            pq.push({-dist[ch], ch});
          }
        }
      }
      if (*std::max_element(dist.begin(), dist.end()) <= k) {
        ans = std::min(ans, {__builtin_popcount(mask), mask});
      }
    }
    std::cout << ans.first << '\n';
    for (ll i = 0; i < n; ++i) {
      if (ans.second & (1 << i)) {
        std::cout << i + 1 << ' ';
      }
    }
    std::cout << '\n';
    return 0;
  }

  // dp[node][0] => you need to cover parent
  // dp[node][1] => parent covers you
  // dp[node][2] => you only need to cover your subtree
  std::vector<std::vector<ll>> dp(n + 1, std::vector<ll>(3, 1e15));
  std::vector<bool> is_leaf(n + 1, true);
  std::function<void(ll, ll, ll)> dfs;
  dfs = [&](ll node, ll par, ll wt) {
    ll sum = 0;
    for (auto &[ch, w] : adj[node]) {
      if (ch == par) {
        continue;
      }
      is_leaf[node] = false;
      dfs(ch, node, w);
      sum += dp[ch][2];
    }
    if (is_leaf[node]) {
      dp[node][0] = wt <= k ? 1 : 1e15;
      dp[node][1] = wt <= k ? 0 : 1e15;
      dp[node][2] = 1;
    } else {
      dp[node][0] = 1;
      dp[node][1] = 0;
      for (auto &[ch, w] : adj[node]) {
        if (ch == par) {
          continue;
        }
        if (w <= k) {
          dp[node][2] = std::min(dp[node][2], sum - dp[ch][2] + dp[ch][0]);
          dp[node][0] += dp[ch][1];
        } else {
          dp[node][0] += dp[ch][2];
        }
        dp[node][1] += dp[ch][2];
      }
      dp[node][1] = std::min(dp[node][1], dp[node][0]);
      dp[node][2] = std::min(dp[node][2], dp[node][0]);
    }
  };
  dfs(1, 0, 0);

  std::vector<ll> ans;
  std::function<void(ll, ll, ll)> build_ans;
  build_ans = [&](ll node, ll par, ll j) {
    if (is_leaf[node]) {
      if (j == 0 or j == 2) {
        ans.push_back(node);
      }
      return;
    }
    if (j == 0) {
      ans.push_back(node);
      for (auto &[ch, w] : adj[node]) {
        if (ch == par) {
          continue;
        }
        if (w <= k) {
          build_ans(ch, node, 1);
        } else {
          build_ans(ch, node, 2);
        }
      }
    } else if (j == 1) {
      if (dp[node][1] == dp[node][0]) {
        build_ans(node, par, 0);
        return;
      }
      for (auto &[ch, w] : adj[node]) {
        if (ch == par) {
          continue;
        }
        build_ans(ch, node, 2);
      }
    } else {
      if (dp[node][2] == dp[node][0]) {
        build_ans(node, par, 0);
        return;
      }
      ll sum = 0;
      for (auto &[ch, w] : adj[node]) {
        if (ch == par) {
          continue;
        }
        sum += dp[ch][2];
      }
      bool found = false;
      for (auto &[ch, w] : adj[node]) {
        if (ch == par) {
          continue;
        }
        if (!found and dp[node][2] == sum - dp[ch][2] + dp[ch][0]) {
          found = true;
          build_ans(ch, node, 0);
        } else {
          build_ans(ch, node, 2);
        }
      }
    }
  };
  build_ans(1, 0, 2);
  std::cout << dp[1][2] << '\n';
  for (auto &i : ans) {
    std::cout << i << ' ';
  }
  std::cout << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...