結果
問題 | No.1789 Tree Growing |
ユーザー |
👑 |
提出日時 | 2021-12-18 00:26:49 |
言語 | D (dmd 2.109.1) |
結果 |
TLE
|
実行時間 | - |
コード長 | 6,203 bytes |
コンパイル時間 | 763 ms |
コンパイル使用メモリ | 123,616 KB |
実行使用メモリ | 18,024 KB |
最終ジャッジ日時 | 2024-06-22 13:46:18 |
合計ジャッジ時間 | 17,014 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 57 TLE * 1 -- * 27 |
ソースコード
import std.conv, std.functional, std.range, std.stdio, std.string;import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;import core.bitop;class EOFException : Throwable { this() { super("EOF"); } }string[] tokens;string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }int readInt() { return readToken.to!int; }long readLong() { return readToken.to!long; }real readReal() { return readToken.to!real; }bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1;(unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }// Dijkstraclass MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {int n, m;int[][] g;int[] as, bs;Capa[] capa;Cost[] cost, pot;Capa tof;Cost toc;this(int n) {this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];}int addEdge(int u, int v, Capa w, Cost c) {debug {// writeln("addEdge ", u, " ", v, " ", w, " ", c);}const i = m;g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;return i;}bool solve(int source, int sink, Capa flow) {pot = new Cost[n];pot[] = 0;for (; ; ) {bool cont;foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {const v = bs[i];if (pot[v] > pot[u] + cost[i]) {pot[v] = pot[u] + cost[i];cont = true;}}if (!cont) break;}auto dist = new Cost[n];auto prei = new int[n];auto vis = new bool[n];for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {/*alias Entry = Tuple!(Cost, "c", int, "u");BinaryHeap!(Array!Entry, "a > b") que;*/dist[] = -1;prei[] = -1;vis[] = false;dist[source] = 0;prei[source] = -2;/*que.insert(Entry(0, source));for (; !que.empty(); ) {const c = que.front.c;const u = que.front.u;que.removeFront;if (vis[u]) continue;vis[u] = true;foreach (i; g[u]) if (capa[i] > CAPA_EPS) {const v = bs[i];if (vis[v]) continue;const cc = c + cost[i] + pot[u] - pot[v];if (prei[v] == -1 || dist[v] > cc) {dist[v] = cc;prei[v] = i;que.insert(Entry(cc, v));}}}*/for (; ; ) {int um = -1;foreach (u; 0 .. n) if (!vis[u] && ~dist[u]) {if (!~um || dist[um] > dist[u]) {um = u;}}if (!~um) {break;}vis[um] = true;foreach (i; g[um]) if (capa[i] > CAPA_EPS) {const v = bs[i];if (!vis[v]) {const cc = dist[um] + cost[i] + pot[um] - pot[v];if (!~dist[v] || dist[v] > cc) {dist[v] = cc;prei[v] = i;}}}}if (!vis[sink]) return false;Capa f = flow - tof;for (int v = sink; v != source; ) {const i = prei[v];if (f > capa[i]) f = capa[i];v = as[i];}for (int v = sink; v != source; ) {const i = prei[v];capa[i] -= f; capa[i ^ 1] += f;v = as[i];}tof += f;toc += f * (dist[sink] - pot[source] + pot[sink]);pot[] += dist[];}return true;}}int[2] N;int[][2] A, B;int[][][2] G;int[int] cache;int calc(int u0, int p0, int u1, int p1) {const key = u0 | p0 << 8 | u1 << 16 | p1 << 24;auto ptr = key in cache;if (ptr) {return *ptr;}int[2] vsLens;int[][2] vss;foreach (h; 0 .. 2) {const u = (h == 0) ? u0 : u1;const p = (h == 0) ? p0 : p1;foreach (i; G[h][u]) {const v = A[h][i] ^ B[h][i] ^ u;if (v != p) {vss[h] ~= v;}}vsLens[h] = cast(int)(vss[h].length);}auto mcf = new MinCostFlow!(int, int)(2 + vsLens[0] + vsLens[1]);foreach (x; 0 .. vsLens[0]) {mcf.addEdge(0, 2 + x, 1, 0);}foreach (y; 0 .. vsLens[1]) {mcf.addEdge(2 + vsLens[0] + y, 1, 1, 0);}foreach (x; 0 .. vsLens[0]) foreach (y; 0 .. vsLens[1]) {const score = calcSub(vss[0][x], u0, vss[1][y], u1);if (score >= 0) {mcf.addEdge(2 + x, 2 + vsLens[0] + y, 1, -(1 + score));}}const status = mcf.solve(0, 1, vsLens[0]);const ret = status ? -mcf.toc : -1;return cache[key] = ret;}int[int] cacheSub;int calcSub(int u0, int p0, int u1, int p1) {const key = u0 | p0 << 8 | u1 << 16 | p1 << 24;auto ptr = key in cacheSub;if (ptr) {return *ptr;}int ret = calc(u0, p0, u1, p1);foreach (i; G[1][u1]) {const v1 = A[1][i] ^ B[1][i] ^ u1;if (v1 != p1) {const res = calcSub(u0, p0, v1, u1);if (res >= 0) {chmax(ret, 1 + res);}}}return cacheSub[key] = ret;}void main() {try {for (; ; ) {foreach (h; 0 .. 2) {N[h] = readInt;A[h] = new int[N[h] - 1];B[h] = new int[N[h] - 1];foreach (i; 0 .. N[h] - 1) {A[h][i] = readInt - 1;B[h][i] = readInt - 1;}}foreach (h; 0 .. 2) {G[h] = new int[][N[h]];foreach (i; 0 .. N[h] - 1) {G[h][A[h][i]] ~= i;G[h][B[h][i]] ~= i;}}cache.clear;cacheSub.clear;int ans = -1;foreach (r0; 0 .. N[0]) foreach (r1; 0 .. N[1]) {chmax(ans, calc(r0, N[0], r1, N[1]));}writeln(ans);}} catch (EOFException e) {}}