Submission #521969

#TimeUsernameProblemLanguageResultExecution timeMemory
521969cadmiumskyMin-max tree (BOI18_minmaxtree)C++14
100 / 100
431 ms58752 KiB
#include <bits/stdc++.h> #define ll long long using namespace std; const int nmax = 7e4 + 5; const int inf = 1e9 + 1; #define pushb push_back pair<int,int> vec[nmax]; int ptrx = 0; struct CuplajDeFraieri { struct edg { int u, v, cap, flow = 0; edg(int c, int a, int b) : u(c), v(a), cap(b) {;} }; vector<int> ptr; vector<int> level; vector<edg> edge; vector<vector<int > > g; int n, s, t; CuplajDeFraieri(int a, int b, int c) : n(a), s(b), t(c) { ptr.resize(n + 1); level.resize(n + 1); g.resize(n + 1); } void push(int u, int v, int cap) { g[u].push_back(edge.size()); edge.pushb(edg(u, v, cap)); g[v].push_back(edge.size()); edge.pushb(edg(v, u, 0)); } queue<int> que; bool bfs() { if(que.empty()) return 0; int node = que.front(); que.pop(); if(node == t) return 1; for(auto x : g[node]) { if(level[edge[x].v] == -1 && edge[x].flow < edge[x].cap ) { que.push(edge[x].v); level[edge[x].v] = level[node] + 1; } } return bfs(); } int dfs(int node, int mn = inf) { if(node == t) return mn; for(int &i = ptr[node]; i < g[node].size(); i++) { int x = g[node][i]; if(edge[x].flow >= edge[x].cap || level[edge[x].v] != level[node] + 1) continue; int temp = dfs(edge[x].v, min(edge[x].cap - edge[x].flow, mn)); if(temp == 0) continue; edge[x].flow += temp; edge[x ^ 1].flow -= temp; return temp; } return 0; } void get() { while(1) { fill(level.begin(), level.end(), -1); level[s] = 0; que = queue<int>(); que.push(s); if(!bfs()) break; fill(ptr.begin(), ptr.end(), 0); while(dfs(s)); } for(auto x : edge) { if(x.u == s) continue; if(x.v == t) continue; if(x.cap == 0) continue; if(x.flow == 1) vec[ptrx++] = {x.u, x.v}; } return; } }; struct edg { int u, other, mn, mx; }; edg edge[nmax]; int pedge[nmax]; vector<int> g[nmax]; namespace LCA { int dpmn[nmax][17]; int dpmx[nmax][17]; int father[nmax][17]; int pin[nmax], pout[nmax]; int inp = 0; void init(int node, int f) { //cout << node << ' ' <<f << '\n'; father[node][0] = f; dpmn[node][0] = -inf; dpmx[node][0] = inf; for(int i = 1; i < 17; i++) { father[node][i] = father[father[node][i - 1]][i - 1]; dpmn[node][i] = -inf; dpmx[node][i] = inf; } int c; pin[node] = inp++; for(auto x : g[node]) { c = edge[x].other ^ node; if(c == f) { pedge[node] = x; continue; } init(c, node); } pout[node] = inp - 1; return; } inline bool isanc(int f, int node) { return pin[f] <= pin[node] && pout[node] <= pout[f]; } void add(char ch, int x, int y, int val) { //cout << "! " << x + 1 << ' ' << y + 1 << ' '<< val << '\n'; for(int i = 16; i >= 0; i--) { if(!isanc(father[x][i], y)) { //cout << x + 1 << ' '<< father[x][i] + 1 << ' '<< val << '\n'; (ch == 'M'? dpmx[x][i] = min(dpmx[x][i], val) : dpmn[x][i] = max(dpmn[x][i], val)); x = father[x][i]; } } if(!isanc(x, y)) { //cout << x + 1 << ' '<< father[x][0] + 1 << ' '<< val << '\n'; (ch == 'M'? dpmx[x][0] = min(dpmx[x][0], val) : dpmn[x][0] = max(dpmn[x][0], val)); } for(int i = 16; i >= 0; i--) { if(!isanc(father[y][i], x)) { //cout << y + 1 << ' '<< father[y][i] + 1 << ' '<< val << '\n'; (ch == 'M'? dpmx[y][i] = min(dpmx[y][i], val) : dpmn[y][i] = max(dpmn[y][i], val)); y = father[y][i]; } } if(!isanc(y, x)) { //cout << y + 1 << ' '<< father[y][0] + 1 << ' '<< val << '\n'; (ch == 'M'? dpmx[y][0] = min(dpmx[y][0], val) : dpmn[y][0] = max(dpmn[y][0], val)); } return; } void mkdp(int node, int f) { for(auto x : g[node]) { int c = edge[x].other ^ node; if(c == f) continue; mkdp(c, node); } for(int i = 16; i > 0; i--) { dpmx[node][i - 1] = min(dpmx[node][i], dpmx[node][i - 1]); dpmx[father[node][i - 1]][i - 1] = min(dpmx[node][i], dpmx[father[node][i - 1]][i - 1]); dpmn[node][i - 1] = max(dpmn[node][i], dpmn[node][i - 1]); dpmn[father[node][i - 1]][i - 1] = max(dpmn[node][i], dpmn[father[node][i - 1]][i - 1]); } //cout << "> " << node + 1 << ' ' << dpmx[node][0] << ' '<<dpmn[node][0] << '\n'; if(node != f) { edge[pedge[node]].mn = dpmn[node][0]; edge[pedge[node]].mx = dpmx[node][0]; } return; } }; #define norm sad map<int,int> norm; map<int,int> inv; int main() { int n; cin >> n; for(int i = 1, x, y; i < n; i++) { cin >> x >> y; --x; --y; g[x].push_back(i); g[y].push_back(i); edge[i] = edg{x, x ^ y, -inf, inf}; } LCA::init(0,0); int q; cin >> q; char ch; for(int i = 0, x, y, w; i < q; i++) { cin >> ch >> x>> y >> w; --x; --y; norm[w]; LCA::add(ch, x, y, w); } LCA::mkdp(0,0); int normax = n + 2; for(auto &x : norm) { x.second = normax; inv[x.second] = x.first; normax++; } int cnt = 2; const int S = 0, T = 1; CuplajDeFraieri flux(normax + 5, S, T); for(int i = n + 2; i < normax; i++) flux.push(S, i, 1); for(int i = 1; i < n; i++) { auto x = edge[i]; if(x.mn == x.mx) x.mx = inf; if(x.mn != -inf) flux.push(norm[x.mn], cnt, 1); if(x.mx != inf) flux.push(norm[x.mx], cnt, 1); flux.push(cnt, T, 1); cnt++; } flux.get(); for(int i = 0; i < ptrx; i++) { auto x = vec[i]; //cout << x.second - 2 << ' ' << inv[x.first] << '\n'; edge[x.second - 1].mx = inv[x.first]; } for(int i = 1; i < n; i++) { auto x = edge[i]; cout << x.u + 1 << ' ' << (x.other ^ x.u) + 1 << ' ' << min(x.mx, inf - 1) << '\n'; } }

Compilation message (stderr)

minmaxtree.cpp: In member function 'int CuplajDeFraieri::dfs(int, int)':
minmaxtree.cpp:50:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   50 |     for(int &i = ptr[node]; i < g[node].size(); i++) {
      |                             ~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...