Submission #1268339

#TimeUsernameProblemLanguageResultExecution timeMemory
1268339aegMin-max tree (BOI18_minmaxtree)C++20
100 / 100
231 ms35116 KiB
#include <bits/stdc++.h>
using namespace std;

vector<pair<int, pair<int, int>>> minis, maxis;

vector<vector<int>> adj;

vector<int> par;
vector<int> height;
vector<int> maxl, minl;

void dfs(int s, int p) {
  par[s] = p;
  for (auto &x : adj[s])
    if (x != p) {
      height[x] = height[s] + 1;
      dfs(x, s);
    }
}

struct dsu {
  vector<int> par;
  dsu(int n) : par(n) {
    for (int i = 0; i < n; i++)
      par[i] = i;
  }

  int find(int a) {
    if (par[a] == a)
      return a;
    return par[a] = find(par[a]);
  }

  void unify(int a, int b) {
    a = find(a), b = find(b);
    if (a == b)
      return;
    if (height[a] > height[b])
      swap(a, b);
    par[b] = a;
  }
};

struct dinic {
  vector<vector<int>> adj;
  struct flowEdge {
    int v, u;
    bool cap;
    flowEdge(int v, int u, bool cap) : v(v), u(u), cap(cap) {}
  };
  vector<flowEdge> edges;
  int n, m = 0;
  int s, t;
  vector<int> lvl, ptr;

  dinic(int n)
      : n(n), lvl(n, 0), ptr(n, 0), adj(n, vector<int>()), s(0), t(n - 1) {}

  void add_edge(int u, int v) {
    edges.emplace_back(u, v, true);
    edges.emplace_back(v, u, false);
    adj[u].emplace_back(m++);
    adj[v].emplace_back(m++);
  }

  queue<int> q;
  bool bfs() {
    while (!q.empty()) {
      int v = q.front();
      q.pop();
      for (int i : adj[v]) {
        if (!edges[i].cap)
          continue;
        if (lvl[edges[i].u] != -1)
          continue;
        lvl[edges[i].u] = lvl[v] + 1;
        q.push(edges[i].u);
      }
    }
    return lvl[t] != -1;
  }

  bool dfs(int v, bool push) {
    if (!push)
      return 0;
    if (v == t)
      return push;

    for (int &cid = ptr[v]; cid < adj[v].size(); cid++) {
      int id = adj[v][cid];
      int u = edges[id].u;
      if (lvl[v] + 1 != lvl[u])
        continue;
      bool tr = dfs(u, edges[id].cap);
      if (!tr)
        continue;
      edges[id].cap = false;
      edges[id ^ 1].cap = true;
      return tr;
    }
    return false;
  }

  int flow() {
    int f = 0;
    while (true) {
      fill(lvl.begin(), lvl.end(), -1);
      lvl[s] = 0;
      q.push(s);
      if (!bfs())
        break;
      fill(ptr.begin(), ptr.end(), 0);
      while (bool push = dfs(s, true)) {
        f++;
      }
    }
    return f;
  }
};

int main() {
  cin.tie(0)->sync_with_stdio(0);
  int n;
  cin >> n;
  adj = vector<vector<int>>(n, vector<int>());
  par = height = vector<int>(n, 0);
  maxl = minl = vector<int>(n, -1);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    adj[a].push_back(b);
    adj[b].push_back(a);
  }

  dfs(0, -1);

  int k;
  cin >> k;
  map<int, int> dict;
  vector<int> revdict(k);
  for (int i = 0; i < k; i++) {
    char c;
    int x, y, z;
    cin >> c >> x >> y >> z;
    x--;
    y--;
    if (c == 'm')
      minis.emplace_back(z, pair<int, int>{x, y});
    else
      maxis.emplace_back(z, pair<int, int>{x, y});

    dict[z] = i;
    revdict[i] = z;
  }

  sort(maxis.begin(), maxis.end());
  sort(minis.begin(), minis.end(), greater<pair<int, pair<int, int>>>());

  dsu uf(n);

  for (int i = 0; i < maxis.size(); i++) {
    auto [l, r] = maxis[i].second;
    int val = maxis[i].first;
    l = uf.find(l), r = uf.find(r);
    while (l != r) {
      if (height[r] > height[l])
        swap(r, l);
      maxl[l] = val;
      uf.unify(l, par[l]);
      l = uf.find(l), r = uf.find(r);
    }
  }

  dsu uf2(n);

  for (int i = 0; i < minis.size(); i++) {
    auto [l, r] = minis[i].second;
    int val = minis[i].first;
    l = uf2.find(l), r = uf2.find(r);
    while (l != r) {
      if (height[r] > height[l])
        swap(r, l);
      minl[l] = val;
      uf2.unify(l, par[l]);
      l = uf2.find(l), r = uf2.find(r);
    }
  }

  // copy(minl.begin(), minl.end(), ostream_iterator<int>(cout, " "));
  // cout << '\n';
  // copy(maxl.begin(), maxl.end(), ostream_iterator<int>(cout, " "));
  // cout << '\n';

  // 0 = source
  // 1 -- n - 1 = edges
  // n -- n + k - 1 = values
  // n + k = target
  dinic flow(n + k + 1);
  for (int i = 1; i < n; i++)
    flow.add_edge(0, i);
  for (int i = 1; i < n; i++) {
    if (minl[i] != -1)
      flow.add_edge(i, n + dict[minl[i]]);
    if (maxl[i] != -1)
      flow.add_edge(i, n + dict[maxl[i]]);
  }
  for (int i = n; i < n + k; i++)
    flow.add_edge(i, n + k);

  int debug = flow.flow();
  if (debug != k)
    return -1;
  vector<int> ans(n, -1);
  for (int i = 0; i < flow.edges.size(); i++) {
    if (flow.edges[i].cap == false && flow.edges[i].v < n &&
        flow.edges[i].u >= n)
      ans[flow.edges[i].v] = revdict[flow.edges[i].u - n];
  }
  for (int i = 1; i < n; i++)
    if (ans[i] == -1) {
      if (minl[i] == -1)
        ans[i] = 0;
      else
        ans[i] = minl[i];
    }

  for (int i = 1; i < n; i++) {
    cout << i + 1 << ' ' << par[i] + 1 << ' ' << ans[i] << '\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...