#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 4e18; // large number for costs / flows
// =====================================================================
// This file contains a collection of Minimum Cost Maximum Flow (MCMF)
// and related Network Flow algorithms. Each function is ready to be used
// as a "black box".
// Read the comments above each one to understand:
// - What it solves
// - What input it expects
// - What it returns
// - Time complexity
// - Important constraints / assumptions
// =====================================================================
// =====================================================================
// 1) STANDARD MIN-COST MAX-FLOW (MCMF) WITH SPFA
// Safest and simplest. Handles negative edge costs.
// Use when graph is small or costs are negative.
// =====================================================================
struct MCMF_SPFA {
struct Edge {
int to, rev; // destination, index of reverse edge
int cap; // remaining capacity
ll cost; // cost per unit of flow
};
int n;
vector<vector<Edge>> adj;
MCMF_SPFA(int n) : n(n), adj(n) {}
// Adds a directed edge u->v with given capacity and cost.
// Also adds the reverse edge (cap 0, cost -cost).
void addEdge(int u, int v, int cap, ll cost) {
Edge a{v, (int)adj[v].size(), cap, cost};
Edge b{u, (int)adj[u].size(), 0, -cost};
adj[u].push_back(a);
adj[v].push_back(b);
}
// Sends flow from s to t while minimizing total cost.
// If maxf == 0, sends as much as possible.
// Returns pair {flow, cost}.
// Complexity: O(flow * E * V) worst-case, but usually O(flow * E).
// Precondition: no negative cost cycles reachable from s.
pair<int, ll> minCostMaxFlow(int s, int t, int maxf = 0) {
int flow = 0;
ll cost = 0;
while (true) {
vector<ll> dist(n, INF);
vector<int> pv(n, -1), pe(n, -1);
vector<bool> inq(n, false);
queue<int> q;
dist[s] = 0;
q.push(s);
inq[s] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
inq[u] = false;
for (int i = 0; i < (int)adj[u].size(); i++) {
Edge &e = adj[u][i];
if (e.cap > 0 && dist[e.to] > dist[u] + e.cost) {
dist[e.to] = dist[u] + e.cost;
pv[e.to] = u;
pe[e.to] = i;
if (!inq[e.to]) {
q.push(e.to);
inq[e.to] = true;
}
}
}
}
if (dist[t] == INF) break;
int add = (maxf == 0) ? INT_MAX : maxf;
for (int v = t; v != s; v = pv[v]) {
add = min(add, adj[pv[v]][pe[v]].cap);
}
if (maxf != 0 && flow + add > maxf) add = maxf - flow;
for (int v = t; v != s; v = pv[v]) {
Edge &e = adj[pv[v]][pe[v]];
e.cap -= add;
adj[v][e.rev].cap += add;
cost += (ll)add * e.cost;
}
flow += add;
if (maxf != 0 && flow == maxf) break;
}
return {flow, cost};
}
};
// =====================================================================
// 2) MIN-COST MAX-FLOW WITH DIJKSTRA + POTENTIALS (FAST)
// Use this for large graphs. Handles negative costs via initial SPFA.
// Complexity: O(flow * E log V).
// =====================================================================
struct MCMF_Dijkstra {
struct Edge {
int to, rev, cap;
ll cost;
};
int n;
vector<vector<Edge>> adj;
vector<ll> pot; // Johnson potentials
MCMF_Dijkstra(int n) : n(n), adj(n), pot(n, 0) {}
void addEdge(int u, int v, int cap, ll cost) {
Edge a{v, (int)adj[v].size(), cap, cost};
Edge b{u, (int)adj[u].size(), 0, -cost};
adj[u].push_back(a);
adj[v].push_back(b);
}
// Sends flow from s to t with minimum cost.
// If maxf == 0, sends as much as possible.
// Returns {flow, cost}.
// Precondition: no negative cost cycles.
pair<int, ll> minCostMaxFlow(int s, int t, int maxf = 0) {
const ll INFLL = INF;
int flow = 0;
ll cost = 0;
// Initial potentials via SPFA (handles negative edges safely)
vector<ll> dist(n, INFLL);
vector<bool> inq(n, false);
queue<int> q;
dist[s] = 0;
q.push(s);
inq[s] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
inq[u] = false;
for (auto &e : adj[u]) {
if (e.cap > 0 && dist[e.to] > dist[u] + e.cost) {
dist[e.to] = dist[u] + e.cost;
if (!inq[e.to]) {
q.push(e.to);
inq[e.to] = true;
}
}
}
}
for (int i = 0; i < n; i++) {
if (dist[i] < INFLL) pot[i] = dist[i];
}
while (true) {
fill(dist.begin(), dist.end(), INFLL);
vector<int> pv(n, -1), pe(n, -1);
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> pq;
dist[s] = 0;
pq.push({0, s});
while (!pq.empty()) {
auto [d, u] = pq.top(); pq.pop();
if (d != dist[u]) continue;
for (int i = 0; i < (int)adj[u].size(); i++) {
Edge &e = adj[u][i];
if (e.cap <= 0) continue;
ll nd = d + e.cost + pot[u] - pot[e.to];
if (dist[e.to] > nd) {
dist[e.to] = nd;
pv[e.to] = u;
pe[e.to] = i;
pq.push({nd, e.to});
}
}
}
if (dist[t] == INFLL) break;
for (int i = 0; i < n; i++) {
if (dist[i] < INFLL) pot[i] += dist[i];
}
int add = (maxf == 0) ? INT_MAX : maxf;
for (int v = t; v != s; v = pv[v]) {
add = min(add, adj[pv[v]][pe[v]].cap);
}
if (maxf != 0 && flow + add > maxf) add = maxf - flow;
for (int v = t; v != s; v = pv[v]) {
Edge &e = adj[pv[v]][pe[v]];
e.cap -= add;
adj[v][e.rev].cap += add;
cost += (ll)add * e.cost;
}
flow += add;
if (maxf != 0 && flow == maxf) break;
}
return {flow, cost};
}
};
// =====================================================================
// 3) MAX FLOW (DINIC)
// Use when only maximum flow is needed (no costs).
// Complexity: O(E * V^2) worst-case, but fast in practice.
// =====================================================================
struct Dinic {
struct Edge {
int to, rev, cap;
};
int n;
vector<vector<Edge>> adj;
vector<int> level, ptr;
Dinic(int n) : n(n), adj(n), level(n), ptr(n) {}
void addEdge(int u, int v, int cap) {
Edge a{v, (int)adj[v].size(), cap};
Edge b{u, (int)adj[u].size(), 0};
adj[u].push_back(a);
adj[v].push_back(b);
}
bool bfs(int s, int t) {
fill(level.begin(), level.end(), -1);
queue<int> q;
level[s] = 0;
q.push(s);
while (!q.empty()) {
int u = q.front(); q.pop();
for (auto &e : adj[u]) {
if (e.cap > 0 && level[e.to] == -1) {
level[e.to] = level[u] + 1;
q.push(e.to);
}
}
}
return level[t] != -1;
}
int dfs(int u, int t, int pushed) {
if (pushed == 0) return 0;
if (u == t) return pushed;
for (int &cid = ptr[u]; cid < (int)adj[u].size(); cid++) {
Edge &e = adj[u][cid];
if (e.cap <= 0 || level[e.to] != level[u] + 1) continue;
int tr = dfs(e.to, t, min(pushed, e.cap));
if (tr == 0) continue;
e.cap -= tr;
adj[e.to][e.rev].cap += tr;
return tr;
}
return 0;
}
int maxFlow(int s, int t) {
int flow = 0;
while (bfs(s, t)) {
fill(ptr.begin(), ptr.end(), 0);
while (int pushed = dfs(s, t, INT_MAX)) {
flow += pushed;
}
}
return flow;
}
};
// =====================================================================
// 4) HUNGARIAN ALGORITHM (ASSIGNMENT PROBLEM)
// Solves min-cost perfect matching for n rows and m columns (n <= m).
// If n > m, it transposes the matrix (each column gets matched to a row).
// Complexity: O(n^2 * m).
// =====================================================================
// Returns {minCost, assignment} where assignment[i] = column assigned to row i.
// If n > m, some rows may have assignment = -1 (meaning unmatched).
pair<ll, vector<int>> hungarian(const vector<vector<ll>> &a) {
int n = (int)a.size();
int m = (int)a[0].size();
// If more rows than columns, transpose so that rows <= columns.
if (n > m) {
vector<vector<ll>> trans(m, vector<ll>(n));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
trans[j][i] = a[i][j];
auto res = hungarian(trans); // res.second has size m (original columns)
vector<int> origAssign(n, -1);
for (int j = 0; j < m; j++) {
int row = res.second[j]; // original row matched to column j
origAssign[row] = j;
}
return {res.first, origAssign};
}
// Standard Hungarian for n <= m
vector<ll> u(n + 1), v(m + 1), p(m + 1), way(m + 1);
for (int i = 1; i <= n; i++) {
p[0] = i;
int j0 = 0;
vector<ll> minv(m + 1, INF);
vector<bool> used(m + 1, false);
do {
used[j0] = true;
int i0 = p[j0];
ll delta = INF;
int j1 = 0;
for (int j = 1; j <= m; j++) {
if (!used[j]) {
ll cur = a[i0 - 1][j - 1] - u[i0] - v[j];
if (cur < minv[j]) {
minv[j] = cur;
way[j] = j0;
}
if (minv[j] < delta) {
delta = minv[j];
j1 = j;
}
}
}
for (int j = 0; j <= m; j++) {
if (used[j]) {
u[p[j]] += delta;
v[j] -= delta;
} else {
minv[j] -= delta;
}
}
j0 = j1;
} while (p[j0] != 0);
do {
int j1 = way[j0];
p[j0] = p[j1];
j0 = j1;
} while (j0);
}
vector<int> assignment(n);
for (int j = 1; j <= m; j++) {
if (p[j] > 0) assignment[p[j] - 1] = j - 1;
}
ll cost = -v[0];
return {cost, assignment};
}
// =====================================================================
// 5) MIN-COST FLOW WITH LOWER BOUNDS
// Some edges must carry at least 'low' units. Finds min-cost circulation
// with an optional s-t flow requirement.
// =====================================================================
// edges: (u, v, low, high, cost)
// Returns {flowSent, totalCost}. If infeasible, returns {-1, -1}.
// 'flowSent' is the amount of flow on the t->s edge (i.e., the s-t flow).
pair<int, ll> minCostFlowWithLowerBounds(
int n,
vector<tuple<int, int, int, int, ll>> edges, // u, v, low, high, cost
int s, int t,
int req = 0 // required s-t flow; 0 means any
) {
int SS = n, TT = n + 1;
MCMF_Dijkstra mcmf(n + 2);
vector<ll> demand(n, 0);
ll baseCost = 0;
// Add edges with adjusted capacities and accumulate demands
for (auto &[u, v, low, high, cost] : edges) {
demand[u] -= low;
demand[v] += low;
baseCost += low * cost;
mcmf.addEdge(u, v, high - low, cost);
}
// Add t->s edge with capacity = req (or INF if req==0)
int capTS = (req == 0) ? INT_MAX : req;
int idxTS = (int)mcmf.adj[t].size(); // forward edge index in adj[t]
mcmf.addEdge(t, s, capTS, 0);
// Add super source/sink edges based on demands
ll totalDemand = 0;
for (int i = 0; i < n; i++) {
if (demand[i] > 0) {
mcmf.addEdge(SS, i, (int)demand[i], 0);
totalDemand += demand[i];
} else if (demand[i] < 0) {
mcmf.addEdge(i, TT, (int)(-demand[i]), 0);
}
}
// Run MCMF from SS to TT, send as much as possible
auto [flow, cost] = mcmf.minCostMaxFlow(SS, TT, 0);
if (flow != totalDemand) {
return {-1, -1}; // infeasible
}
// Compute actual flow on t->s edge
int flowOnTS = capTS - mcmf.adj[t][idxTS].cap;
return {flowOnTS, cost + baseCost};
}
// =====================================================================
// 6) HELPER FUNCTIONS FOR COMMON PATTERNS
// =====================================================================
// 6.1) MIN-COST FLOW WITH VERTEX CAPACITIES (NODE SPLITTING)
// Each node can handle at most vertexCap[i] units of flow.
// If vertexCap[i] == 0, it means infinite.
// Returns {flow, cost}.
pair<int, ll> minCostFlowWithVertexCaps(
int n,
vector<tuple<int, int, int, ll>> edges, // (u, v, cap, cost)
vector<int> vertexCap, // size n
int s, int t,
int maxFlow = 0
) {
int N = 2 * n + 2;
int SS = 2 * n;
int TT = 2 * n + 1;
MCMF_Dijkstra mcmf(N);
// Vertex capacity edges: in(v) -> out(v)
for (int v = 0; v < n; v++) {
int cap = (vertexCap[v] == 0) ? INT_MAX / 2 : vertexCap[v];
mcmf.addEdge(2 * v, 2 * v + 1, cap, 0);
}
// Original edges: out(u) -> in(v)
for (auto &[u, v, cap, cost] : edges) {
mcmf.addEdge(2 * u + 1, 2 * v, cap, cost);
}
// Super source -> s_in, t_out -> super sink
int req = (maxFlow == 0) ? INT_MAX / 2 : maxFlow;
mcmf.addEdge(SS, 2 * s, req, 0);
mcmf.addEdge(2 * t + 1, TT, req, 0);
auto [flow, cost] = mcmf.minCostMaxFlow(SS, TT, maxFlow);
return {flow, cost};
}
// 6.2) MULTI-SOURCE / MULTI-SINK MIN-COST FLOW
// Sources have supplies, sinks have demands.
// Returns {flow, cost}.
pair<int, ll> multiSourceSinkMCMF(
int n,
vector<tuple<int, int, int, ll>> edges,
vector<pair<int, int>> sources, // (node, supply)
vector<pair<int, int>> sinks, // (node, demand)
int maxFlow = 0
) {
int SS = n, TT = n + 1;
MCMF_Dijkstra mcmf(n + 2);
for (auto &[u, v, cap, cost] : edges) {
mcmf.addEdge(u, v, cap, cost);
}
ll totalSupply = 0;
for (auto &[node, supply] : sources) {
mcmf.addEdge(SS, node, supply, 0);
totalSupply += supply;
}
ll totalDemand = 0;
for (auto &[node, demand] : sinks) {
mcmf.addEdge(node, TT, demand, 0);
totalDemand += demand;
}
int req = (maxFlow == 0) ? (int)min(totalSupply, totalDemand) : maxFlow;
auto [flow, cost] = mcmf.minCostMaxFlow(SS, TT, req);
return {flow, cost};
}
// 6.3) MAX PROFIT FLOW (negate profits and run MCMF)
pair<int, ll> maxProfitFlow(
int n,
vector<tuple<int, int, int, ll>> edges, // (u, v, cap, profit)
int s, int t,
int maxFlow = 0
) {
vector<tuple<int, int, int, ll>> costEdges;
for (auto &[u, v, cap, profit] : edges) {
costEdges.emplace_back(u, v, cap, -profit);
}
MCMF_Dijkstra mcmf(n);
for (auto &[u, v, cap, cost] : costEdges) {
mcmf.addEdge(u, v, cap, cost);
}
auto [flow, minCost] = mcmf.minCostMaxFlow(s, t, maxFlow);
return {flow, -minCost};
}
// 6.4) MAXIMUM WEIGHT BIPARTITE MATCHING (dense)
// Uses Hungarian after negating profits.
// Returns {maxProfit, assignment} (assignment may have -1 for unmatched rows).
pair<ll, vector<int>> maxWeightBipartiteMatching(const vector<vector<ll>>& profitMatrix) {
int n = profitMatrix.size();
int m = profitMatrix[0].size();
vector<vector<ll>> costMatrix(n, vector<ll>(m));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
costMatrix[i][j] = -profitMatrix[i][j];
auto [minCost, assignment] = hungarian(costMatrix);
return {-minCost, assignment};
}
// 6.5) MINIMUM PATH COVER IN A DAG (unweighted)
// Returns the minimum number of vertex-disjoint paths covering all nodes.
int minPathCoverCount(int n, const vector<pair<int, int>>& dagEdges) {
int total = 2 * n + 2;
int S = 2 * n, T = 2 * n + 1;
Dinic dinic(total);
for (int i = 0; i < n; i++) {
dinic.addEdge(S, i, 1);
dinic.addEdge(n + i, T, 1);
}
for (auto &[u, v] : dagEdges) {
dinic.addEdge(u, n + v, 1);
}
int maxMatching = dinic.maxFlow(S, T);
return n - maxMatching;
}
// 6.6) MINIMUM COST PATH COVER IN A DAG (weighted)
// Returns {numberOfPaths, minTotalCost}.
pair<int, ll> minCostPathCover(int n, const vector<tuple<int, int, ll>>& dagEdges) {
int S = 2 * n, T = 2 * n + 1;
MCMF_Dijkstra mcmf(2 * n + 2);
for (int i = 0; i < n; i++) {
mcmf.addEdge(S, i, 1, 0);
mcmf.addEdge(n + i, T, 1, 0);
}
for (auto &[u, v, cost] : dagEdges) {
mcmf.addEdge(u, n + v, 1, cost);
}
auto [flow, cost] = mcmf.minCostMaxFlow(S, T, 0);
int paths = n - flow;
return {paths, cost};
}
// =====================================================================
// EXAMPLE USAGE (remove in production)
// =====================================================================
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Example 1: Basic MCMF (SPFA)
MCMF_SPFA mcmf1(4);
mcmf1.addEdge(0, 1, 10, 2);
mcmf1.addEdge(0, 2, 10, 3);
mcmf1.addEdge(1, 3, 5, 1);
mcmf1.addEdge(2, 3, 10, 4);
auto res1 = mcmf1.minCostMaxFlow(0, 3);
cout << "SPFA MCMF: Flow=" << res1.first << ", Cost=" << res1.second << "\n";
// Example 2: Hungarian
vector<vector<ll>> costMatrix = {
{4, 1, 3},
{2, 0, 5},
{3, 2, 2}
};
auto res2 = hungarian(costMatrix);
cout << "Hungarian: Min Cost=" << res2.first << "\nAssignment: ";
for (int x : res2.second) cout << x << " ";
cout << "\n";
// Example 3: Dinic max flow
Dinic dinic(4);
dinic.addEdge(0, 1, 10);
dinic.addEdge(0, 2, 10);
dinic.addEdge(1, 3, 5);
dinic.addEdge(2, 3, 10);
cout << "Dinic Max Flow: " << dinic.maxFlow(0, 3) << "\n";
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp1c2luZyBsbCA9IGxvbmcgbG9uZzsKY29uc3QgbGwgSU5GID0gNGUxODsgLy8gbGFyZ2UgbnVtYmVyIGZvciBjb3N0cyAvIGZsb3dzCgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gVGhpcyBmaWxlIGNvbnRhaW5zIGEgY29sbGVjdGlvbiBvZiBNaW5pbXVtIENvc3QgTWF4aW11bSBGbG93IChNQ01GKQovLyBhbmQgcmVsYXRlZCBOZXR3b3JrIEZsb3cgYWxnb3JpdGhtcy4gRWFjaCBmdW5jdGlvbiBpcyByZWFkeSB0byBiZSB1c2VkCi8vIGFzIGEgImJsYWNrIGJveCIuCi8vIFJlYWQgdGhlIGNvbW1lbnRzIGFib3ZlIGVhY2ggb25lIHRvIHVuZGVyc3RhbmQ6Ci8vICAgLSBXaGF0IGl0IHNvbHZlcwovLyAgIC0gV2hhdCBpbnB1dCBpdCBleHBlY3RzCi8vICAgLSBXaGF0IGl0IHJldHVybnMKLy8gICAtIFRpbWUgY29tcGxleGl0eQovLyAgIC0gSW1wb3J0YW50IGNvbnN0cmFpbnRzIC8gYXNzdW1wdGlvbnMKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gMSkgU1RBTkRBUkQgTUlOLUNPU1QgTUFYLUZMT1cgKE1DTUYpIFdJVEggU1BGQQovLyAgICBTYWZlc3QgYW5kIHNpbXBsZXN0LiBIYW5kbGVzIG5lZ2F0aXZlIGVkZ2UgY29zdHMuCi8vICAgIFVzZSB3aGVuIGdyYXBoIGlzIHNtYWxsIG9yIGNvc3RzIGFyZSBuZWdhdGl2ZS4KLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgpzdHJ1Y3QgTUNNRl9TUEZBIHsKICAgIHN0cnVjdCBFZGdlIHsKICAgICAgICBpbnQgdG8sIHJldjsgICAvLyBkZXN0aW5hdGlvbiwgaW5kZXggb2YgcmV2ZXJzZSBlZGdlCiAgICAgICAgaW50IGNhcDsgICAgICAgLy8gcmVtYWluaW5nIGNhcGFjaXR5CiAgICAgICAgbGwgY29zdDsgICAgICAgLy8gY29zdCBwZXIgdW5pdCBvZiBmbG93CiAgICB9OwoKICAgIGludCBuOwogICAgdmVjdG9yPHZlY3RvcjxFZGdlPj4gYWRqOwoKICAgIE1DTUZfU1BGQShpbnQgbikgOiBuKG4pLCBhZGoobikge30KCiAgICAvLyBBZGRzIGEgZGlyZWN0ZWQgZWRnZSB1LT52IHdpdGggZ2l2ZW4gY2FwYWNpdHkgYW5kIGNvc3QuCiAgICAvLyBBbHNvIGFkZHMgdGhlIHJldmVyc2UgZWRnZSAoY2FwIDAsIGNvc3QgLWNvc3QpLgogICAgdm9pZCBhZGRFZGdlKGludCB1LCBpbnQgdiwgaW50IGNhcCwgbGwgY29zdCkgewogICAgICAgIEVkZ2UgYXt2LCAoaW50KWFkalt2XS5zaXplKCksIGNhcCwgY29zdH07CiAgICAgICAgRWRnZSBie3UsIChpbnQpYWRqW3VdLnNpemUoKSwgMCwgLWNvc3R9OwogICAgICAgIGFkalt1XS5wdXNoX2JhY2soYSk7CiAgICAgICAgYWRqW3ZdLnB1c2hfYmFjayhiKTsKICAgIH0KCiAgICAvLyBTZW5kcyBmbG93IGZyb20gcyB0byB0IHdoaWxlIG1pbmltaXppbmcgdG90YWwgY29zdC4KICAgIC8vIElmIG1heGYgPT0gMCwgc2VuZHMgYXMgbXVjaCBhcyBwb3NzaWJsZS4KICAgIC8vIFJldHVybnMgcGFpciB7ZmxvdywgY29zdH0uCiAgICAvLyBDb21wbGV4aXR5OiBPKGZsb3cgKiBFICogVikgd29yc3QtY2FzZSwgYnV0IHVzdWFsbHkgTyhmbG93ICogRSkuCiAgICAvLyBQcmVjb25kaXRpb246IG5vIG5lZ2F0aXZlIGNvc3QgY3ljbGVzIHJlYWNoYWJsZSBmcm9tIHMuCiAgICBwYWlyPGludCwgbGw+IG1pbkNvc3RNYXhGbG93KGludCBzLCBpbnQgdCwgaW50IG1heGYgPSAwKSB7CiAgICAgICAgaW50IGZsb3cgPSAwOwogICAgICAgIGxsIGNvc3QgPSAwOwoKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICB2ZWN0b3I8bGw+IGRpc3QobiwgSU5GKTsKICAgICAgICAgICAgdmVjdG9yPGludD4gcHYobiwgLTEpLCBwZShuLCAtMSk7CiAgICAgICAgICAgIHZlY3Rvcjxib29sPiBpbnEobiwgZmFsc2UpOwogICAgICAgICAgICBxdWV1ZTxpbnQ+IHE7CgogICAgICAgICAgICBkaXN0W3NdID0gMDsKICAgICAgICAgICAgcS5wdXNoKHMpOwogICAgICAgICAgICBpbnFbc10gPSB0cnVlOwoKICAgICAgICAgICAgd2hpbGUgKCFxLmVtcHR5KCkpIHsKICAgICAgICAgICAgICAgIGludCB1ID0gcS5mcm9udCgpOyBxLnBvcCgpOwogICAgICAgICAgICAgICAgaW5xW3VdID0gZmFsc2U7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpYWRqW3VdLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgRWRnZSAmZSA9IGFkalt1XVtpXTsKICAgICAgICAgICAgICAgICAgICBpZiAoZS5jYXAgPiAwICYmIGRpc3RbZS50b10gPiBkaXN0W3VdICsgZS5jb3N0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RbZS50b10gPSBkaXN0W3VdICsgZS5jb3N0OwogICAgICAgICAgICAgICAgICAgICAgICBwdltlLnRvXSA9IHU7CiAgICAgICAgICAgICAgICAgICAgICAgIHBlW2UudG9dID0gaTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpbnFbZS50b10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHEucHVzaChlLnRvKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucVtlLnRvXSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChkaXN0W3RdID09IElORikgYnJlYWs7CgogICAgICAgICAgICBpbnQgYWRkID0gKG1heGYgPT0gMCkgPyBJTlRfTUFYIDogbWF4ZjsKICAgICAgICAgICAgZm9yIChpbnQgdiA9IHQ7IHYgIT0gczsgdiA9IHB2W3ZdKSB7CiAgICAgICAgICAgICAgICBhZGQgPSBtaW4oYWRkLCBhZGpbcHZbdl1dW3BlW3ZdXS5jYXApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChtYXhmICE9IDAgJiYgZmxvdyArIGFkZCA+IG1heGYpIGFkZCA9IG1heGYgLSBmbG93OwoKICAgICAgICAgICAgZm9yIChpbnQgdiA9IHQ7IHYgIT0gczsgdiA9IHB2W3ZdKSB7CiAgICAgICAgICAgICAgICBFZGdlICZlID0gYWRqW3B2W3ZdXVtwZVt2XV07CiAgICAgICAgICAgICAgICBlLmNhcCAtPSBhZGQ7CiAgICAgICAgICAgICAgICBhZGpbdl1bZS5yZXZdLmNhcCArPSBhZGQ7CiAgICAgICAgICAgICAgICBjb3N0ICs9IChsbClhZGQgKiBlLmNvc3Q7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZmxvdyArPSBhZGQ7CgogICAgICAgICAgICBpZiAobWF4ZiAhPSAwICYmIGZsb3cgPT0gbWF4ZikgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7ZmxvdywgY29zdH07CiAgICB9Cn07CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gMikgTUlOLUNPU1QgTUFYLUZMT1cgV0lUSCBESUpLU1RSQSArIFBPVEVOVElBTFMgKEZBU1QpCi8vICAgIFVzZSB0aGlzIGZvciBsYXJnZSBncmFwaHMuIEhhbmRsZXMgbmVnYXRpdmUgY29zdHMgdmlhIGluaXRpYWwgU1BGQS4KLy8gICAgQ29tcGxleGl0eTogTyhmbG93ICogRSBsb2cgVikuCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKc3RydWN0IE1DTUZfRGlqa3N0cmEgewogICAgc3RydWN0IEVkZ2UgewogICAgICAgIGludCB0bywgcmV2LCBjYXA7CiAgICAgICAgbGwgY29zdDsKICAgIH07CgogICAgaW50IG47CiAgICB2ZWN0b3I8dmVjdG9yPEVkZ2U+PiBhZGo7CiAgICB2ZWN0b3I8bGw+IHBvdDsgLy8gSm9obnNvbiBwb3RlbnRpYWxzCgogICAgTUNNRl9EaWprc3RyYShpbnQgbikgOiBuKG4pLCBhZGoobiksIHBvdChuLCAwKSB7fQoKICAgIHZvaWQgYWRkRWRnZShpbnQgdSwgaW50IHYsIGludCBjYXAsIGxsIGNvc3QpIHsKICAgICAgICBFZGdlIGF7diwgKGludClhZGpbdl0uc2l6ZSgpLCBjYXAsIGNvc3R9OwogICAgICAgIEVkZ2UgYnt1LCAoaW50KWFkalt1XS5zaXplKCksIDAsIC1jb3N0fTsKICAgICAgICBhZGpbdV0ucHVzaF9iYWNrKGEpOwogICAgICAgIGFkalt2XS5wdXNoX2JhY2soYik7CiAgICB9CgogICAgLy8gU2VuZHMgZmxvdyBmcm9tIHMgdG8gdCB3aXRoIG1pbmltdW0gY29zdC4KICAgIC8vIElmIG1heGYgPT0gMCwgc2VuZHMgYXMgbXVjaCBhcyBwb3NzaWJsZS4KICAgIC8vIFJldHVybnMge2Zsb3csIGNvc3R9LgogICAgLy8gUHJlY29uZGl0aW9uOiBubyBuZWdhdGl2ZSBjb3N0IGN5Y2xlcy4KICAgIHBhaXI8aW50LCBsbD4gbWluQ29zdE1heEZsb3coaW50IHMsIGludCB0LCBpbnQgbWF4ZiA9IDApIHsKICAgICAgICBjb25zdCBsbCBJTkZMTCA9IElORjsKICAgICAgICBpbnQgZmxvdyA9IDA7CiAgICAgICAgbGwgY29zdCA9IDA7CgogICAgICAgIC8vIEluaXRpYWwgcG90ZW50aWFscyB2aWEgU1BGQSAoaGFuZGxlcyBuZWdhdGl2ZSBlZGdlcyBzYWZlbHkpCiAgICAgICAgdmVjdG9yPGxsPiBkaXN0KG4sIElORkxMKTsKICAgICAgICB2ZWN0b3I8Ym9vbD4gaW5xKG4sIGZhbHNlKTsKICAgICAgICBxdWV1ZTxpbnQ+IHE7CiAgICAgICAgZGlzdFtzXSA9IDA7CiAgICAgICAgcS5wdXNoKHMpOwogICAgICAgIGlucVtzXSA9IHRydWU7CgogICAgICAgIHdoaWxlICghcS5lbXB0eSgpKSB7CiAgICAgICAgICAgIGludCB1ID0gcS5mcm9udCgpOyBxLnBvcCgpOwogICAgICAgICAgICBpbnFbdV0gPSBmYWxzZTsKICAgICAgICAgICAgZm9yIChhdXRvICZlIDogYWRqW3VdKSB7CiAgICAgICAgICAgICAgICBpZiAoZS5jYXAgPiAwICYmIGRpc3RbZS50b10gPiBkaXN0W3VdICsgZS5jb3N0KSB7CiAgICAgICAgICAgICAgICAgICAgZGlzdFtlLnRvXSA9IGRpc3RbdV0gKyBlLmNvc3Q7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFpbnFbZS50b10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgcS5wdXNoKGUudG8pOwogICAgICAgICAgICAgICAgICAgICAgICBpbnFbZS50b10gPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgaWYgKGRpc3RbaV0gPCBJTkZMTCkgcG90W2ldID0gZGlzdFtpXTsKICAgICAgICB9CgogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIGZpbGwoZGlzdC5iZWdpbigpLCBkaXN0LmVuZCgpLCBJTkZMTCk7CiAgICAgICAgICAgIHZlY3RvcjxpbnQ+IHB2KG4sIC0xKSwgcGUobiwgLTEpOwogICAgICAgICAgICBwcmlvcml0eV9xdWV1ZTxwYWlyPGxsLCBpbnQ+LCB2ZWN0b3I8cGFpcjxsbCwgaW50Pj4sIGdyZWF0ZXI8cGFpcjxsbCwgaW50Pj4+IHBxOwoKICAgICAgICAgICAgZGlzdFtzXSA9IDA7CiAgICAgICAgICAgIHBxLnB1c2goezAsIHN9KTsKCiAgICAgICAgICAgIHdoaWxlICghcHEuZW1wdHkoKSkgewogICAgICAgICAgICAgICAgYXV0byBbZCwgdV0gPSBwcS50b3AoKTsgcHEucG9wKCk7CiAgICAgICAgICAgICAgICBpZiAoZCAhPSBkaXN0W3VdKSBjb250aW51ZTsKCiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpYWRqW3VdLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgRWRnZSAmZSA9IGFkalt1XVtpXTsKICAgICAgICAgICAgICAgICAgICBpZiAoZS5jYXAgPD0gMCkgY29udGludWU7CgogICAgICAgICAgICAgICAgICAgIGxsIG5kID0gZCArIGUuY29zdCArIHBvdFt1XSAtIHBvdFtlLnRvXTsKICAgICAgICAgICAgICAgICAgICBpZiAoZGlzdFtlLnRvXSA+IG5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RbZS50b10gPSBuZDsKICAgICAgICAgICAgICAgICAgICAgICAgcHZbZS50b10gPSB1OwogICAgICAgICAgICAgICAgICAgICAgICBwZVtlLnRvXSA9IGk7CiAgICAgICAgICAgICAgICAgICAgICAgIHBxLnB1c2goe25kLCBlLnRvfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoZGlzdFt0XSA9PSBJTkZMTCkgYnJlYWs7CgogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgICAgICAgICAgaWYgKGRpc3RbaV0gPCBJTkZMTCkgcG90W2ldICs9IGRpc3RbaV07CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGludCBhZGQgPSAobWF4ZiA9PSAwKSA/IElOVF9NQVggOiBtYXhmOwogICAgICAgICAgICBmb3IgKGludCB2ID0gdDsgdiAhPSBzOyB2ID0gcHZbdl0pIHsKICAgICAgICAgICAgICAgIGFkZCA9IG1pbihhZGQsIGFkaltwdlt2XV1bcGVbdl1dLmNhcCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG1heGYgIT0gMCAmJiBmbG93ICsgYWRkID4gbWF4ZikgYWRkID0gbWF4ZiAtIGZsb3c7CgogICAgICAgICAgICBmb3IgKGludCB2ID0gdDsgdiAhPSBzOyB2ID0gcHZbdl0pIHsKICAgICAgICAgICAgICAgIEVkZ2UgJmUgPSBhZGpbcHZbdl1dW3BlW3ZdXTsKICAgICAgICAgICAgICAgIGUuY2FwIC09IGFkZDsKICAgICAgICAgICAgICAgIGFkalt2XVtlLnJldl0uY2FwICs9IGFkZDsKICAgICAgICAgICAgICAgIGNvc3QgKz0gKGxsKWFkZCAqIGUuY29zdDsKICAgICAgICAgICAgfQogICAgICAgICAgICBmbG93ICs9IGFkZDsKCiAgICAgICAgICAgIGlmIChtYXhmICE9IDAgJiYgZmxvdyA9PSBtYXhmKSBicmVhazsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHtmbG93LCBjb3N0fTsKICAgIH0KfTsKCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAzKSBNQVggRkxPVyAoRElOSUMpCi8vICAgIFVzZSB3aGVuIG9ubHkgbWF4aW11bSBmbG93IGlzIG5lZWRlZCAobm8gY29zdHMpLgovLyAgICBDb21wbGV4aXR5OiBPKEUgKiBWXjIpIHdvcnN0LWNhc2UsIGJ1dCBmYXN0IGluIHByYWN0aWNlLgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCnN0cnVjdCBEaW5pYyB7CiAgICBzdHJ1Y3QgRWRnZSB7CiAgICAgICAgaW50IHRvLCByZXYsIGNhcDsKICAgIH07CgogICAgaW50IG47CiAgICB2ZWN0b3I8dmVjdG9yPEVkZ2U+PiBhZGo7CiAgICB2ZWN0b3I8aW50PiBsZXZlbCwgcHRyOwoKICAgIERpbmljKGludCBuKSA6IG4obiksIGFkaihuKSwgbGV2ZWwobiksIHB0cihuKSB7fQoKICAgIHZvaWQgYWRkRWRnZShpbnQgdSwgaW50IHYsIGludCBjYXApIHsKICAgICAgICBFZGdlIGF7diwgKGludClhZGpbdl0uc2l6ZSgpLCBjYXB9OwogICAgICAgIEVkZ2UgYnt1LCAoaW50KWFkalt1XS5zaXplKCksIDB9OwogICAgICAgIGFkalt1XS5wdXNoX2JhY2soYSk7CiAgICAgICAgYWRqW3ZdLnB1c2hfYmFjayhiKTsKICAgIH0KCiAgICBib29sIGJmcyhpbnQgcywgaW50IHQpIHsKICAgICAgICBmaWxsKGxldmVsLmJlZ2luKCksIGxldmVsLmVuZCgpLCAtMSk7CiAgICAgICAgcXVldWU8aW50PiBxOwogICAgICAgIGxldmVsW3NdID0gMDsKICAgICAgICBxLnB1c2gocyk7CiAgICAgICAgd2hpbGUgKCFxLmVtcHR5KCkpIHsKICAgICAgICAgICAgaW50IHUgPSBxLmZyb250KCk7IHEucG9wKCk7CiAgICAgICAgICAgIGZvciAoYXV0byAmZSA6IGFkalt1XSkgewogICAgICAgICAgICAgICAgaWYgKGUuY2FwID4gMCAmJiBsZXZlbFtlLnRvXSA9PSAtMSkgewogICAgICAgICAgICAgICAgICAgIGxldmVsW2UudG9dID0gbGV2ZWxbdV0gKyAxOwogICAgICAgICAgICAgICAgICAgIHEucHVzaChlLnRvKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbGV2ZWxbdF0gIT0gLTE7CiAgICB9CgogICAgaW50IGRmcyhpbnQgdSwgaW50IHQsIGludCBwdXNoZWQpIHsKICAgICAgICBpZiAocHVzaGVkID09IDApIHJldHVybiAwOwogICAgICAgIGlmICh1ID09IHQpIHJldHVybiBwdXNoZWQ7CiAgICAgICAgZm9yIChpbnQgJmNpZCA9IHB0clt1XTsgY2lkIDwgKGludClhZGpbdV0uc2l6ZSgpOyBjaWQrKykgewogICAgICAgICAgICBFZGdlICZlID0gYWRqW3VdW2NpZF07CiAgICAgICAgICAgIGlmIChlLmNhcCA8PSAwIHx8IGxldmVsW2UudG9dICE9IGxldmVsW3VdICsgMSkgY29udGludWU7CiAgICAgICAgICAgIGludCB0ciA9IGRmcyhlLnRvLCB0LCBtaW4ocHVzaGVkLCBlLmNhcCkpOwogICAgICAgICAgICBpZiAodHIgPT0gMCkgY29udGludWU7CiAgICAgICAgICAgIGUuY2FwIC09IHRyOwogICAgICAgICAgICBhZGpbZS50b11bZS5yZXZdLmNhcCArPSB0cjsKICAgICAgICAgICAgcmV0dXJuIHRyOwogICAgICAgIH0KICAgICAgICByZXR1cm4gMDsKICAgIH0KCiAgICBpbnQgbWF4RmxvdyhpbnQgcywgaW50IHQpIHsKICAgICAgICBpbnQgZmxvdyA9IDA7CiAgICAgICAgd2hpbGUgKGJmcyhzLCB0KSkgewogICAgICAgICAgICBmaWxsKHB0ci5iZWdpbigpLCBwdHIuZW5kKCksIDApOwogICAgICAgICAgICB3aGlsZSAoaW50IHB1c2hlZCA9IGRmcyhzLCB0LCBJTlRfTUFYKSkgewogICAgICAgICAgICAgICAgZmxvdyArPSBwdXNoZWQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZsb3c7CiAgICB9Cn07CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gNCkgSFVOR0FSSUFOIEFMR09SSVRITSAoQVNTSUdOTUVOVCBQUk9CTEVNKQovLyAgICBTb2x2ZXMgbWluLWNvc3QgcGVyZmVjdCBtYXRjaGluZyBmb3IgbiByb3dzIGFuZCBtIGNvbHVtbnMgKG4gPD0gbSkuCi8vICAgIElmIG4gPiBtLCBpdCB0cmFuc3Bvc2VzIHRoZSBtYXRyaXggKGVhY2ggY29sdW1uIGdldHMgbWF0Y2hlZCB0byBhIHJvdykuCi8vICAgIENvbXBsZXhpdHk6IE8obl4yICogbSkuCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKLy8gUmV0dXJucyB7bWluQ29zdCwgYXNzaWdubWVudH0gd2hlcmUgYXNzaWdubWVudFtpXSA9IGNvbHVtbiBhc3NpZ25lZCB0byByb3cgaS4KLy8gSWYgbiA+IG0sIHNvbWUgcm93cyBtYXkgaGF2ZSBhc3NpZ25tZW50ID0gLTEgKG1lYW5pbmcgdW5tYXRjaGVkKS4KcGFpcjxsbCwgdmVjdG9yPGludD4+IGh1bmdhcmlhbihjb25zdCB2ZWN0b3I8dmVjdG9yPGxsPj4gJmEpIHsKICAgIGludCBuID0gKGludClhLnNpemUoKTsKICAgIGludCBtID0gKGludClhWzBdLnNpemUoKTsKCiAgICAvLyBJZiBtb3JlIHJvd3MgdGhhbiBjb2x1bW5zLCB0cmFuc3Bvc2Ugc28gdGhhdCByb3dzIDw9IGNvbHVtbnMuCiAgICBpZiAobiA+IG0pIHsKICAgICAgICB2ZWN0b3I8dmVjdG9yPGxsPj4gdHJhbnMobSwgdmVjdG9yPGxsPihuKSk7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgbTsgaisrKQogICAgICAgICAgICAgICAgdHJhbnNbal1baV0gPSBhW2ldW2pdOwogICAgICAgIGF1dG8gcmVzID0gaHVuZ2FyaWFuKHRyYW5zKTsgLy8gcmVzLnNlY29uZCBoYXMgc2l6ZSBtIChvcmlnaW5hbCBjb2x1bW5zKQogICAgICAgIHZlY3RvcjxpbnQ+IG9yaWdBc3NpZ24obiwgLTEpOwogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgbTsgaisrKSB7CiAgICAgICAgICAgIGludCByb3cgPSByZXMuc2Vjb25kW2pdOyAvLyBvcmlnaW5hbCByb3cgbWF0Y2hlZCB0byBjb2x1bW4gagogICAgICAgICAgICBvcmlnQXNzaWduW3Jvd10gPSBqOwogICAgICAgIH0KICAgICAgICByZXR1cm4ge3Jlcy5maXJzdCwgb3JpZ0Fzc2lnbn07CiAgICB9CgogICAgLy8gU3RhbmRhcmQgSHVuZ2FyaWFuIGZvciBuIDw9IG0KICAgIHZlY3RvcjxsbD4gdShuICsgMSksIHYobSArIDEpLCBwKG0gKyAxKSwgd2F5KG0gKyAxKTsKICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG47IGkrKykgewogICAgICAgIHBbMF0gPSBpOwogICAgICAgIGludCBqMCA9IDA7CiAgICAgICAgdmVjdG9yPGxsPiBtaW52KG0gKyAxLCBJTkYpOwogICAgICAgIHZlY3Rvcjxib29sPiB1c2VkKG0gKyAxLCBmYWxzZSk7CiAgICAgICAgZG8gewogICAgICAgICAgICB1c2VkW2owXSA9IHRydWU7CiAgICAgICAgICAgIGludCBpMCA9IHBbajBdOwogICAgICAgICAgICBsbCBkZWx0YSA9IElORjsKICAgICAgICAgICAgaW50IGoxID0gMDsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IDE7IGogPD0gbTsgaisrKSB7CiAgICAgICAgICAgICAgICBpZiAoIXVzZWRbal0pIHsKICAgICAgICAgICAgICAgICAgICBsbCBjdXIgPSBhW2kwIC0gMV1baiAtIDFdIC0gdVtpMF0gLSB2W2pdOwogICAgICAgICAgICAgICAgICAgIGlmIChjdXIgPCBtaW52W2pdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIG1pbnZbal0gPSBjdXI7CiAgICAgICAgICAgICAgICAgICAgICAgIHdheVtqXSA9IGowOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAobWludltqXSA8IGRlbHRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlbHRhID0gbWludltqXTsKICAgICAgICAgICAgICAgICAgICAgICAgajEgPSBqOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8PSBtOyBqKyspIHsKICAgICAgICAgICAgICAgIGlmICh1c2VkW2pdKSB7CiAgICAgICAgICAgICAgICAgICAgdVtwW2pdXSArPSBkZWx0YTsKICAgICAgICAgICAgICAgICAgICB2W2pdIC09IGRlbHRhOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBtaW52W2pdIC09IGRlbHRhOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGowID0gajE7CiAgICAgICAgfSB3aGlsZSAocFtqMF0gIT0gMCk7CgogICAgICAgIGRvIHsKICAgICAgICAgICAgaW50IGoxID0gd2F5W2owXTsKICAgICAgICAgICAgcFtqMF0gPSBwW2oxXTsKICAgICAgICAgICAgajAgPSBqMTsKICAgICAgICB9IHdoaWxlIChqMCk7CiAgICB9CgogICAgdmVjdG9yPGludD4gYXNzaWdubWVudChuKTsKICAgIGZvciAoaW50IGogPSAxOyBqIDw9IG07IGorKykgewogICAgICAgIGlmIChwW2pdID4gMCkgYXNzaWdubWVudFtwW2pdIC0gMV0gPSBqIC0gMTsKICAgIH0KICAgIGxsIGNvc3QgPSAtdlswXTsKICAgIHJldHVybiB7Y29zdCwgYXNzaWdubWVudH07Cn0KCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyA1KSBNSU4tQ09TVCBGTE9XIFdJVEggTE9XRVIgQk9VTkRTCi8vICAgIFNvbWUgZWRnZXMgbXVzdCBjYXJyeSBhdCBsZWFzdCAnbG93JyB1bml0cy4gRmluZHMgbWluLWNvc3QgY2lyY3VsYXRpb24KLy8gICAgd2l0aCBhbiBvcHRpb25hbCBzLXQgZmxvdyByZXF1aXJlbWVudC4KLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyBlZGdlczogKHUsIHYsIGxvdywgaGlnaCwgY29zdCkKLy8gUmV0dXJucyB7Zmxvd1NlbnQsIHRvdGFsQ29zdH0uIElmIGluZmVhc2libGUsIHJldHVybnMgey0xLCAtMX0uCi8vICdmbG93U2VudCcgaXMgdGhlIGFtb3VudCBvZiBmbG93IG9uIHRoZSB0LT5zIGVkZ2UgKGkuZS4sIHRoZSBzLXQgZmxvdykuCnBhaXI8aW50LCBsbD4gbWluQ29zdEZsb3dXaXRoTG93ZXJCb3VuZHMoCiAgICBpbnQgbiwKICAgIHZlY3Rvcjx0dXBsZTxpbnQsIGludCwgaW50LCBpbnQsIGxsPj4gZWRnZXMsIC8vIHUsIHYsIGxvdywgaGlnaCwgY29zdAogICAgaW50IHMsIGludCB0LAogICAgaW50IHJlcSA9IDAgICAgICAgICAgLy8gcmVxdWlyZWQgcy10IGZsb3c7IDAgbWVhbnMgYW55CikgewogICAgaW50IFNTID0gbiwgVFQgPSBuICsgMTsKICAgIE1DTUZfRGlqa3N0cmEgbWNtZihuICsgMik7CgogICAgdmVjdG9yPGxsPiBkZW1hbmQobiwgMCk7CiAgICBsbCBiYXNlQ29zdCA9IDA7CgogICAgLy8gQWRkIGVkZ2VzIHdpdGggYWRqdXN0ZWQgY2FwYWNpdGllcyBhbmQgYWNjdW11bGF0ZSBkZW1hbmRzCiAgICBmb3IgKGF1dG8gJlt1LCB2LCBsb3csIGhpZ2gsIGNvc3RdIDogZWRnZXMpIHsKICAgICAgICBkZW1hbmRbdV0gLT0gbG93OwogICAgICAgIGRlbWFuZFt2XSArPSBsb3c7CiAgICAgICAgYmFzZUNvc3QgKz0gbG93ICogY29zdDsKICAgICAgICBtY21mLmFkZEVkZ2UodSwgdiwgaGlnaCAtIGxvdywgY29zdCk7CiAgICB9CgogICAgLy8gQWRkIHQtPnMgZWRnZSB3aXRoIGNhcGFjaXR5ID0gcmVxIChvciBJTkYgaWYgcmVxPT0wKQogICAgaW50IGNhcFRTID0gKHJlcSA9PSAwKSA/IElOVF9NQVggOiByZXE7CiAgICBpbnQgaWR4VFMgPSAoaW50KW1jbWYuYWRqW3RdLnNpemUoKTsgLy8gZm9yd2FyZCBlZGdlIGluZGV4IGluIGFkalt0XQogICAgbWNtZi5hZGRFZGdlKHQsIHMsIGNhcFRTLCAwKTsKCiAgICAvLyBBZGQgc3VwZXIgc291cmNlL3NpbmsgZWRnZXMgYmFzZWQgb24gZGVtYW5kcwogICAgbGwgdG90YWxEZW1hbmQgPSAwOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBpZiAoZGVtYW5kW2ldID4gMCkgewogICAgICAgICAgICBtY21mLmFkZEVkZ2UoU1MsIGksIChpbnQpZGVtYW5kW2ldLCAwKTsKICAgICAgICAgICAgdG90YWxEZW1hbmQgKz0gZGVtYW5kW2ldOwogICAgICAgIH0gZWxzZSBpZiAoZGVtYW5kW2ldIDwgMCkgewogICAgICAgICAgICBtY21mLmFkZEVkZ2UoaSwgVFQsIChpbnQpKC1kZW1hbmRbaV0pLCAwKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gUnVuIE1DTUYgZnJvbSBTUyB0byBUVCwgc2VuZCBhcyBtdWNoIGFzIHBvc3NpYmxlCiAgICBhdXRvIFtmbG93LCBjb3N0XSA9IG1jbWYubWluQ29zdE1heEZsb3coU1MsIFRULCAwKTsKCiAgICBpZiAoZmxvdyAhPSB0b3RhbERlbWFuZCkgewogICAgICAgIHJldHVybiB7LTEsIC0xfTsgLy8gaW5mZWFzaWJsZQogICAgfQoKICAgIC8vIENvbXB1dGUgYWN0dWFsIGZsb3cgb24gdC0+cyBlZGdlCiAgICBpbnQgZmxvd09uVFMgPSBjYXBUUyAtIG1jbWYuYWRqW3RdW2lkeFRTXS5jYXA7CiAgICByZXR1cm4ge2Zsb3dPblRTLCBjb3N0ICsgYmFzZUNvc3R9Owp9CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gNikgSEVMUEVSIEZVTkNUSU9OUyBGT1IgQ09NTU9OIFBBVFRFUk5TCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKLy8gNi4xKSBNSU4tQ09TVCBGTE9XIFdJVEggVkVSVEVYIENBUEFDSVRJRVMgKE5PREUgU1BMSVRUSU5HKQovLyAgICAgIEVhY2ggbm9kZSBjYW4gaGFuZGxlIGF0IG1vc3QgdmVydGV4Q2FwW2ldIHVuaXRzIG9mIGZsb3cuCi8vICAgICAgSWYgdmVydGV4Q2FwW2ldID09IDAsIGl0IG1lYW5zIGluZmluaXRlLgovLyAgICAgIFJldHVybnMge2Zsb3csIGNvc3R9LgpwYWlyPGludCwgbGw+IG1pbkNvc3RGbG93V2l0aFZlcnRleENhcHMoCiAgICBpbnQgbiwKICAgIHZlY3Rvcjx0dXBsZTxpbnQsIGludCwgaW50LCBsbD4+IGVkZ2VzLCAvLyAodSwgdiwgY2FwLCBjb3N0KQogICAgdmVjdG9yPGludD4gdmVydGV4Q2FwLCAgICAgICAgICAgICAgICAgIC8vIHNpemUgbgogICAgaW50IHMsIGludCB0LAogICAgaW50IG1heEZsb3cgPSAwCikgewogICAgaW50IE4gPSAyICogbiArIDI7CiAgICBpbnQgU1MgPSAyICogbjsKICAgIGludCBUVCA9IDIgKiBuICsgMTsKICAgIE1DTUZfRGlqa3N0cmEgbWNtZihOKTsKCiAgICAvLyBWZXJ0ZXggY2FwYWNpdHkgZWRnZXM6IGluKHYpIC0+IG91dCh2KQogICAgZm9yIChpbnQgdiA9IDA7IHYgPCBuOyB2KyspIHsKICAgICAgICBpbnQgY2FwID0gKHZlcnRleENhcFt2XSA9PSAwKSA/IElOVF9NQVggLyAyIDogdmVydGV4Q2FwW3ZdOwogICAgICAgIG1jbWYuYWRkRWRnZSgyICogdiwgMiAqIHYgKyAxLCBjYXAsIDApOwogICAgfQoKICAgIC8vIE9yaWdpbmFsIGVkZ2VzOiBvdXQodSkgLT4gaW4odikKICAgIGZvciAoYXV0byAmW3UsIHYsIGNhcCwgY29zdF0gOiBlZGdlcykgewogICAgICAgIG1jbWYuYWRkRWRnZSgyICogdSArIDEsIDIgKiB2LCBjYXAsIGNvc3QpOwogICAgfQoKICAgIC8vIFN1cGVyIHNvdXJjZSAtPiBzX2luLCB0X291dCAtPiBzdXBlciBzaW5rCiAgICBpbnQgcmVxID0gKG1heEZsb3cgPT0gMCkgPyBJTlRfTUFYIC8gMiA6IG1heEZsb3c7CiAgICBtY21mLmFkZEVkZ2UoU1MsIDIgKiBzLCByZXEsIDApOwogICAgbWNtZi5hZGRFZGdlKDIgKiB0ICsgMSwgVFQsIHJlcSwgMCk7CgogICAgYXV0byBbZmxvdywgY29zdF0gPSBtY21mLm1pbkNvc3RNYXhGbG93KFNTLCBUVCwgbWF4Rmxvdyk7CiAgICByZXR1cm4ge2Zsb3csIGNvc3R9Owp9CgovLyA2LjIpIE1VTFRJLVNPVVJDRSAvIE1VTFRJLVNJTksgTUlOLUNPU1QgRkxPVwovLyAgICAgIFNvdXJjZXMgaGF2ZSBzdXBwbGllcywgc2lua3MgaGF2ZSBkZW1hbmRzLgovLyAgICAgIFJldHVybnMge2Zsb3csIGNvc3R9LgpwYWlyPGludCwgbGw+IG11bHRpU291cmNlU2lua01DTUYoCiAgICBpbnQgbiwKICAgIHZlY3Rvcjx0dXBsZTxpbnQsIGludCwgaW50LCBsbD4+IGVkZ2VzLAogICAgdmVjdG9yPHBhaXI8aW50LCBpbnQ+PiBzb3VyY2VzLCAvLyAobm9kZSwgc3VwcGx5KQogICAgdmVjdG9yPHBhaXI8aW50LCBpbnQ+PiBzaW5rcywgICAvLyAobm9kZSwgZGVtYW5kKQogICAgaW50IG1heEZsb3cgPSAwCikgewogICAgaW50IFNTID0gbiwgVFQgPSBuICsgMTsKICAgIE1DTUZfRGlqa3N0cmEgbWNtZihuICsgMik7CgogICAgZm9yIChhdXRvICZbdSwgdiwgY2FwLCBjb3N0XSA6IGVkZ2VzKSB7CiAgICAgICAgbWNtZi5hZGRFZGdlKHUsIHYsIGNhcCwgY29zdCk7CiAgICB9CgogICAgbGwgdG90YWxTdXBwbHkgPSAwOwogICAgZm9yIChhdXRvICZbbm9kZSwgc3VwcGx5XSA6IHNvdXJjZXMpIHsKICAgICAgICBtY21mLmFkZEVkZ2UoU1MsIG5vZGUsIHN1cHBseSwgMCk7CiAgICAgICAgdG90YWxTdXBwbHkgKz0gc3VwcGx5OwogICAgfQoKICAgIGxsIHRvdGFsRGVtYW5kID0gMDsKICAgIGZvciAoYXV0byAmW25vZGUsIGRlbWFuZF0gOiBzaW5rcykgewogICAgICAgIG1jbWYuYWRkRWRnZShub2RlLCBUVCwgZGVtYW5kLCAwKTsKICAgICAgICB0b3RhbERlbWFuZCArPSBkZW1hbmQ7CiAgICB9CgogICAgaW50IHJlcSA9IChtYXhGbG93ID09IDApID8gKGludCltaW4odG90YWxTdXBwbHksIHRvdGFsRGVtYW5kKSA6IG1heEZsb3c7CiAgICBhdXRvIFtmbG93LCBjb3N0XSA9IG1jbWYubWluQ29zdE1heEZsb3coU1MsIFRULCByZXEpOwogICAgcmV0dXJuIHtmbG93LCBjb3N0fTsKfQoKLy8gNi4zKSBNQVggUFJPRklUIEZMT1cgKG5lZ2F0ZSBwcm9maXRzIGFuZCBydW4gTUNNRikKcGFpcjxpbnQsIGxsPiBtYXhQcm9maXRGbG93KAogICAgaW50IG4sCiAgICB2ZWN0b3I8dHVwbGU8aW50LCBpbnQsIGludCwgbGw+PiBlZGdlcywgLy8gKHUsIHYsIGNhcCwgcHJvZml0KQogICAgaW50IHMsIGludCB0LAogICAgaW50IG1heEZsb3cgPSAwCikgewogICAgdmVjdG9yPHR1cGxlPGludCwgaW50LCBpbnQsIGxsPj4gY29zdEVkZ2VzOwogICAgZm9yIChhdXRvICZbdSwgdiwgY2FwLCBwcm9maXRdIDogZWRnZXMpIHsKICAgICAgICBjb3N0RWRnZXMuZW1wbGFjZV9iYWNrKHUsIHYsIGNhcCwgLXByb2ZpdCk7CiAgICB9CiAgICBNQ01GX0RpamtzdHJhIG1jbWYobik7CiAgICBmb3IgKGF1dG8gJlt1LCB2LCBjYXAsIGNvc3RdIDogY29zdEVkZ2VzKSB7CiAgICAgICAgbWNtZi5hZGRFZGdlKHUsIHYsIGNhcCwgY29zdCk7CiAgICB9CiAgICBhdXRvIFtmbG93LCBtaW5Db3N0XSA9IG1jbWYubWluQ29zdE1heEZsb3cocywgdCwgbWF4Rmxvdyk7CiAgICByZXR1cm4ge2Zsb3csIC1taW5Db3N0fTsKfQoKLy8gNi40KSBNQVhJTVVNIFdFSUdIVCBCSVBBUlRJVEUgTUFUQ0hJTkcgKGRlbnNlKQovLyAgICAgIFVzZXMgSHVuZ2FyaWFuIGFmdGVyIG5lZ2F0aW5nIHByb2ZpdHMuCi8vICAgICAgUmV0dXJucyB7bWF4UHJvZml0LCBhc3NpZ25tZW50fSAoYXNzaWdubWVudCBtYXkgaGF2ZSAtMSBmb3IgdW5tYXRjaGVkIHJvd3MpLgpwYWlyPGxsLCB2ZWN0b3I8aW50Pj4gbWF4V2VpZ2h0QmlwYXJ0aXRlTWF0Y2hpbmcoY29uc3QgdmVjdG9yPHZlY3RvcjxsbD4+JiBwcm9maXRNYXRyaXgpIHsKICAgIGludCBuID0gcHJvZml0TWF0cml4LnNpemUoKTsKICAgIGludCBtID0gcHJvZml0TWF0cml4WzBdLnNpemUoKTsKICAgIHZlY3Rvcjx2ZWN0b3I8bGw+PiBjb3N0TWF0cml4KG4sIHZlY3RvcjxsbD4obSkpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBtOyBqKyspCiAgICAgICAgICAgIGNvc3RNYXRyaXhbaV1bal0gPSAtcHJvZml0TWF0cml4W2ldW2pdOwogICAgYXV0byBbbWluQ29zdCwgYXNzaWdubWVudF0gPSBodW5nYXJpYW4oY29zdE1hdHJpeCk7CiAgICByZXR1cm4gey1taW5Db3N0LCBhc3NpZ25tZW50fTsKfQoKLy8gNi41KSBNSU5JTVVNIFBBVEggQ09WRVIgSU4gQSBEQUcgKHVud2VpZ2h0ZWQpCi8vICAgICAgUmV0dXJucyB0aGUgbWluaW11bSBudW1iZXIgb2YgdmVydGV4LWRpc2pvaW50IHBhdGhzIGNvdmVyaW5nIGFsbCBub2Rlcy4KaW50IG1pblBhdGhDb3ZlckNvdW50KGludCBuLCBjb25zdCB2ZWN0b3I8cGFpcjxpbnQsIGludD4+JiBkYWdFZGdlcykgewogICAgaW50IHRvdGFsID0gMiAqIG4gKyAyOwogICAgaW50IFMgPSAyICogbiwgVCA9IDIgKiBuICsgMTsKICAgIERpbmljIGRpbmljKHRvdGFsKTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGRpbmljLmFkZEVkZ2UoUywgaSwgMSk7CiAgICAgICAgZGluaWMuYWRkRWRnZShuICsgaSwgVCwgMSk7CiAgICB9CiAgICBmb3IgKGF1dG8gJlt1LCB2XSA6IGRhZ0VkZ2VzKSB7CiAgICAgICAgZGluaWMuYWRkRWRnZSh1LCBuICsgdiwgMSk7CiAgICB9CgogICAgaW50IG1heE1hdGNoaW5nID0gZGluaWMubWF4RmxvdyhTLCBUKTsKICAgIHJldHVybiBuIC0gbWF4TWF0Y2hpbmc7Cn0KCi8vIDYuNikgTUlOSU1VTSBDT1NUIFBBVEggQ09WRVIgSU4gQSBEQUcgKHdlaWdodGVkKQovLyAgICAgIFJldHVybnMge251bWJlck9mUGF0aHMsIG1pblRvdGFsQ29zdH0uCnBhaXI8aW50LCBsbD4gbWluQ29zdFBhdGhDb3ZlcihpbnQgbiwgY29uc3QgdmVjdG9yPHR1cGxlPGludCwgaW50LCBsbD4+JiBkYWdFZGdlcykgewogICAgaW50IFMgPSAyICogbiwgVCA9IDIgKiBuICsgMTsKICAgIE1DTUZfRGlqa3N0cmEgbWNtZigyICogbiArIDIpOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgbWNtZi5hZGRFZGdlKFMsIGksIDEsIDApOwogICAgICAgIG1jbWYuYWRkRWRnZShuICsgaSwgVCwgMSwgMCk7CiAgICB9CiAgICBmb3IgKGF1dG8gJlt1LCB2LCBjb3N0XSA6IGRhZ0VkZ2VzKSB7CiAgICAgICAgbWNtZi5hZGRFZGdlKHUsIG4gKyB2LCAxLCBjb3N0KTsKICAgIH0KCiAgICBhdXRvIFtmbG93LCBjb3N0XSA9IG1jbWYubWluQ29zdE1heEZsb3coUywgVCwgMCk7CiAgICBpbnQgcGF0aHMgPSBuIC0gZmxvdzsKICAgIHJldHVybiB7cGF0aHMsIGNvc3R9Owp9CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gRVhBTVBMRSBVU0FHRSAocmVtb3ZlIGluIHByb2R1Y3Rpb24pCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKaW50IG1haW4oKSB7CiAgICBpb3M6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSk7CiAgICBjaW4udGllKG51bGxwdHIpOwoKICAgIC8vIEV4YW1wbGUgMTogQmFzaWMgTUNNRiAoU1BGQSkKICAgIE1DTUZfU1BGQSBtY21mMSg0KTsKICAgIG1jbWYxLmFkZEVkZ2UoMCwgMSwgMTAsIDIpOwogICAgbWNtZjEuYWRkRWRnZSgwLCAyLCAxMCwgMyk7CiAgICBtY21mMS5hZGRFZGdlKDEsIDMsIDUsIDEpOwogICAgbWNtZjEuYWRkRWRnZSgyLCAzLCAxMCwgNCk7CiAgICBhdXRvIHJlczEgPSBtY21mMS5taW5Db3N0TWF4RmxvdygwLCAzKTsKICAgIGNvdXQgPDwgIlNQRkEgTUNNRjogRmxvdz0iIDw8IHJlczEuZmlyc3QgPDwgIiwgQ29zdD0iIDw8IHJlczEuc2Vjb25kIDw8ICJcbiI7CgogICAgLy8gRXhhbXBsZSAyOiBIdW5nYXJpYW4KICAgIHZlY3Rvcjx2ZWN0b3I8bGw+PiBjb3N0TWF0cml4ID0gewogICAgICAgIHs0LCAxLCAzfSwKICAgICAgICB7MiwgMCwgNX0sCiAgICAgICAgezMsIDIsIDJ9CiAgICB9OwogICAgYXV0byByZXMyID0gaHVuZ2FyaWFuKGNvc3RNYXRyaXgpOwogICAgY291dCA8PCAiSHVuZ2FyaWFuOiBNaW4gQ29zdD0iIDw8IHJlczIuZmlyc3QgPDwgIlxuQXNzaWdubWVudDogIjsKICAgIGZvciAoaW50IHggOiByZXMyLnNlY29uZCkgY291dCA8PCB4IDw8ICIgIjsKICAgIGNvdXQgPDwgIlxuIjsKCiAgICAvLyBFeGFtcGxlIDM6IERpbmljIG1heCBmbG93CiAgICBEaW5pYyBkaW5pYyg0KTsKICAgIGRpbmljLmFkZEVkZ2UoMCwgMSwgMTApOwogICAgZGluaWMuYWRkRWRnZSgwLCAyLCAxMCk7CiAgICBkaW5pYy5hZGRFZGdlKDEsIDMsIDUpOwogICAgZGluaWMuYWRkRWRnZSgyLCAzLCAxMCk7CiAgICBjb3V0IDw8ICJEaW5pYyBNYXggRmxvdzogIiA8PCBkaW5pYy5tYXhGbG93KDAsIDMpIDw8ICJcbiI7CgogICAgcmV0dXJuIDA7Cn0=