답안 #219752

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
219752 2020-04-06T09:05:10 Z rama_pang Designated Cities (JOI19_designated_cities) C++14
6 / 100
591 ms 524292 KB
#include <bits/stdc++.h>
using namespace std;
using lint = long long;

struct edge_t {
  int v;
  int away;
  int come;
  edge_t() {}
  edge_t(int v, int a, int c) : v(v), away(a), come(c) {}
};

int N;
vector<vector<edge_t>> adj;

vector<lint> Answer;
vector<lint> BaseCost; // BaseCost[i] = sum of all edges going to i (root at i), so we do not need to consider them afterwards
vector<bool> processed; // processed as R, done via centroid decomposition

void GenerateBaseCost() {
  vector<lint> dp(N);
  function<void(int, int)> dfs = [&](int n, int p) {
    for (const auto &i : adj[n]) if (i.v != p) {
      dfs(i.v, n);
      dp[n] += dp[i.v] + i.come;
    }
  };

  function<void(int, int)> reroot = [&](int n, int p) {
    BaseCost[n] = dp[n];
    for (const auto &i : adj[n]) if (i.v != p) {
      dp[n] -= dp[i.v] + i.come;
      dp[i.v] += dp[n] + i.away;
      reroot(i.v, n);
      dp[i.v] -= dp[n] + i.away;
      dp[n] += dp[i.v] + i.come;
    }
  };

  dfs(0, -1);
  reroot(0, -1);

}

vector<int> sz; // subtree size

int Centroid(int n) {
  function<void(int, int)> dfs = [&](int n, int p) {
    sz[n] = 1;
    for (const auto &i : adj[n]) if (i.v != p && !processed[i.v]) {
      dfs(i.v, n);
      sz[n] += sz[i.v];
    }
  };

  dfs(n, -1);
  int cur = n, p = -1;
  while (true) {
    pair<int, int> mx = {-1, -1};
    for (const auto &i : adj[cur]) if (i.v != p && !processed[i.v]) {
      mx = max(mx, {sz[i.v], i.v});
    }
    if (mx.first * 2 <= sz[n]) {
      return cur;
    }
    p = cur;
    cur = mx.second;
  }
}

vector<vector<lint>> optimal; // optimal[v][k] = for subtree v, res[k + 1] - res[k] 
                              // where res[k] is the optimal way of picking k nodes in 
                              // subtree of v such that the edge cost away from v is maximum

void Solve(int R) {
  function<void(int, int8_t)> dfs = [&](int n, int p) {
    optimal[n].clear();
    optimal[n].emplace_back(0);
    for (const auto &i : adj[n]) if (i.v != p && !processed[i.v]) {
      dfs(i.v, n);
      optimal[i.v].front() += i.away;
      if (optimal[n].size() < optimal[i.v].size()) {
        swap(optimal[i.v], optimal[n]);
      }
      if (optimal[i.v].front() > optimal[n].front()) {
        swap(optimal[i.v].front(), optimal[n].front());
      }
      for (const auto &j : optimal[i.v]) {
        optimal[n].emplace_back(j);
      }
      optimal[i.v].clear();
    }
  };

  for (const auto &i : adj[R]) if (!processed[i.v]) {
    dfs(i.v, R);
    optimal[i.v].front() += i.away;
  }

  vector<lint> all;
  for (const auto &i : adj[R]) if (!processed[i.v]) {
    all.insert(end(all), begin(optimal[i.v]), end(optimal[i.v]));
  }
  sort(begin(all), end(all), greater<lint>());

  { // Case #1: R is chosen
    lint sum = BaseCost[R]; 
    int cnt = 1;
    Answer[cnt] = max(Answer[cnt], sum);

    for (int i = 0; i < all.size(); i++) {
      sum += all[i], cnt++;
      Answer[cnt] = max(Answer[cnt], sum);
    }
  }

  { // Case #2: R is not chosen, two different subtrees
    pair<lint, lint> mx = {-1, -1};
    for (const auto &i : adj[R]) if (!processed[i.v]) {
      if (optimal[i.v].front() > mx.first) {
        mx.second = mx.first;
        mx.first = optimal[i.v].front();
      } else if (optimal[i.v].front() > mx.second) {
        mx.second = optimal[i.v].front();
      }
    }
    
    if (mx.first != -1 && mx.second != -1) {
     lint sum = BaseCost[R] + mx.first + mx.second; 
      int cnt = 2;
      Answer[cnt] = max(Answer[cnt], sum);

      for (int i = 0; i < all.size(); i++) {
        if (all[i] == mx.first) {
          mx.first = -1;
        } else if (all[i] == mx.second) {
          mx.second = -1;
        } else {
          sum += all[i], cnt++;
          Answer[cnt] = max(Answer[cnt], sum);
        }
      }
    }
  }

  for (const auto &i : adj[R]) if (!processed[i.v]) {
    optimal[i.v].clear();
  }
}

void CentroidDecomposition() {
  queue<int> q;
  q.emplace(0);
  while (!q.empty()) {
    int R = Centroid(q.front());
    q.pop();
    Solve(R);
    processed[R] = true;
    for (const auto &i : adj[R]) if (!processed[i.v]) {
      q.emplace(i.v);
    }
  }
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);

  cin >> N;

  sz.resize(N);  
  adj.resize(N);
  optimal.resize(N);
  BaseCost.resize(N);
  Answer.resize(N + 1);
  processed.resize(N, false);

  lint sum_all_costs = 0;
  for (int i = 0; i < N - 1; i++) {
    int A, B, C, D;
    cin >> A >> B >> C >> D;
    A--, B--;
    adj[A].emplace_back(B, C, D);
    adj[B].emplace_back(A, D, C);
    sum_all_costs += C + D;
  }

  GenerateBaseCost();
  CentroidDecomposition();

  for (int i = 1; i <= N; i++) {
    Answer[i] = max(Answer[i], Answer[i - 1]);
  }
  for (int i = 1; i <= N; i++) {
    Answer[i] = sum_all_costs - Answer[i];
  }

  int Q;
  cin >> Q;
  for (int i = 0; i < Q; i++) {
    int E;
    cin >> E;
    cout << Answer[E] << "\n";
  }

  return 0;
}

Compilation message

designated_cities.cpp: In function 'void Solve(int)':
designated_cities.cpp:111:23: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (int i = 0; i < all.size(); i++) {
                     ~~^~~~~~~~~~~~
designated_cities.cpp:133:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       for (int i = 0; i < all.size(); i++) {
                       ~~^~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Correct 5 ms 384 KB Output is correct
3 Correct 5 ms 384 KB Output is correct
4 Correct 5 ms 384 KB Output is correct
5 Correct 5 ms 384 KB Output is correct
6 Correct 5 ms 384 KB Output is correct
7 Correct 5 ms 384 KB Output is correct
8 Correct 5 ms 384 KB Output is correct
9 Correct 4 ms 384 KB Output is correct
10 Correct 4 ms 384 KB Output is correct
11 Correct 6 ms 384 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Runtime error 591 ms 524292 KB Execution killed with signal 9 (could be triggered by violating memory limits)
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Runtime error 566 ms 524292 KB Execution killed with signal 9 (could be triggered by violating memory limits)
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Correct 5 ms 384 KB Output is correct
3 Correct 5 ms 384 KB Output is correct
4 Correct 5 ms 384 KB Output is correct
5 Correct 5 ms 384 KB Output is correct
6 Correct 5 ms 384 KB Output is correct
7 Correct 5 ms 384 KB Output is correct
8 Correct 5 ms 384 KB Output is correct
9 Correct 4 ms 384 KB Output is correct
10 Correct 4 ms 384 KB Output is correct
11 Correct 6 ms 384 KB Output is correct
12 Correct 5 ms 384 KB Output is correct
13 Runtime error 295 ms 524292 KB Execution killed with signal 9 (could be triggered by violating memory limits)
14 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Runtime error 591 ms 524292 KB Execution killed with signal 9 (could be triggered by violating memory limits)
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Correct 5 ms 384 KB Output is correct
3 Correct 5 ms 384 KB Output is correct
4 Correct 5 ms 384 KB Output is correct
5 Correct 5 ms 384 KB Output is correct
6 Correct 5 ms 384 KB Output is correct
7 Correct 5 ms 384 KB Output is correct
8 Correct 5 ms 384 KB Output is correct
9 Correct 4 ms 384 KB Output is correct
10 Correct 4 ms 384 KB Output is correct
11 Correct 6 ms 384 KB Output is correct
12 Correct 5 ms 384 KB Output is correct
13 Runtime error 591 ms 524292 KB Execution killed with signal 9 (could be triggered by violating memory limits)
14 Halted 0 ms 0 KB -