// #define USACO cow
#include <bits/stdc++.h>
using namespace std;
#define STR_(x) #x
#define STR(x) STR_(x)
using ll = long long;
const ll INF = LLONG_MAX - 10;
ll max(int x, ll y) { return std::max((ll) x, y); }
ll max(ll y, int x) { return std::max((ll) x, y); }
ll min(int x, ll y) { return std::min((ll) x, y); }
ll min(ll y, int x) { return std::min((ll) x, y); }
struct Coordinate
{
ll x, y;
static void sortByX(vector<Coordinate*>& vec)
{
sort(vec.begin(), vec.end(), [](Coordinate* a, Coordinate* b) {
return a->x < b->x;
});
}
static void sortByY(vector<Coordinate*>& vec)
{
sort(vec.begin(), vec.end(), [](Coordinate* a, Coordinate* b) {
return a->y < b->y;
});
}
};
struct Rect
{
ll x1, y1, x2, y2;
friend ostream& operator<<(ostream& os, const Rect& rect)
{
return os << rect.x1 << ' ' << rect.y1 << ' ' << rect.x2 << ' ' << rect.y2;
}
friend istream& operator>>(istream& is, Rect& rect)
{
return is >> rect.x1 >> rect.y1 >> rect.x2 >> rect.y2;
}
};
template<typename Grid>
void cartesianPrint(const Grid& grid, int rows, int cols)
{
if (rows < 0 || cols < 0)
{
throw invalid_argument("rows and cols must be non-negative");
}
vector<int> colWidths(cols);
for (int c = 0; c < cols; ++c)
{
colWidths[c] = static_cast<int>(to_string(c).size());
for (int r = 0; r < rows; ++r)
{
ll value = grid[r][c];
int width = static_cast<int>(to_string(value).size());
colWidths[c] = max(colWidths[c], width);
}
}
int rowLabelWidth = max(3, static_cast<int>(to_string(rows - 1).size()));
// ---- Column labels (TOP) ----
cerr << string(rowLabelWidth, ' ') << " ";
for (int c = 0; c < cols; ++c)
{
cerr << setw(colWidths[c]) << c;
if (c < cols - 1)
{
cerr << ' ';
}
}
cerr << '\n';
cerr << string(rowLabelWidth, ' ') << " +";
for (int c = 0; c < cols; ++c)
{
cerr << string(colWidths[c] + 1, '-');
}
cerr << '\n';
// ---- Rows ----
for (int r = 0; r < rows; ++r)
{
cerr << setw(rowLabelWidth) << r << " | ";
for (int c = 0; c < cols; ++c)
{
cerr << setw(colWidths[c]) << grid[r][c];
if (c < cols - 1)
{
cerr << ' ';
}
}
cerr << '\n';
}
}
const vector<pair<int, int>> dirs = {
{1, 0}, {0, 1}, {-1, 0}, {0, -1},
{1, 1}, {-1, 1}, {-1, -1}, {1, -1}
};
const vector<pair<int, int>> dirs4 = {
{1, 0}, {0, 1}, {-1, 0}, {0, -1}
};
const int MOD = 1000000007;
constexpr double epsilon = 0.00001;
struct MCMF {
struct edge {
int from, to, rev;
ll cap, cost, flow;
};
int N;
vector<vector<edge>> ed;
vector<int> seen;
vector<ll> dist, pi;
vector<edge*> par;
MCMF(int N_in) : N(N_in), ed(N_in), seen(N_in), dist(N_in), pi(N_in), par(N_in) {}
void addEdge(int from, int to, ll cap, ll cost) {
if (from == to) return;
ed[from].push_back(edge{ from,to,(int)ed[to].size(),cap,cost,0 });
ed[to].push_back(edge{ to,from,(int)ed[from].size()-1,0,-cost,0 });
}
void path(int s) {
fill(seen.begin(), seen.end(), 0);
fill(dist.begin(), dist.end(), INF);
dist[s] = 0; ll di;
priority_queue<pair<ll, int>> q;
q.push({ 0, s });
while (!q.empty()) {
s = q.top().second; q.pop();
if (seen[s]) continue; // outdated entry
seen[s] = 1; di = dist[s] + pi[s];
for (edge& e : ed[s]) if (!seen[e.to]) {
ll val = di - pi[e.to] + e.cost;
if (e.cap - e.flow > 0 && val < dist[e.to]) {
dist[e.to] = val;
par[e.to] = &e;
q.push({ -dist[e.to], e.to });
}
}
}
for (int i = 0; i < N; i++) pi[i] = min(pi[i] + dist[i], INF);
}
pair<ll, ll> maxflow(int s, int t) {
ll totflow = 0, totcost = 0;
while (path(s), seen[t]) {
ll fl = INF;
for (edge* x = par[t]; x; x = par[x->from])
fl = min(fl, x->cap - x->flow);
totflow += fl;
for (edge* x = par[t]; x; x = par[x->from]) {
x->flow += fl;
ed[x->to][x->rev].flow -= fl;
}
}
for (int i = 0; i < N; i++) for(edge& e : ed[i]) totcost += e.cost * e.flow;
return {totflow, totcost/2};
}
// If some costs can be negative, call this before maxflow:
void setpi(int s) { // (otherwise, leave this out)
fill(pi.begin(), pi.end(), INF); pi[s] = 0;
int it = N, ch = 1; ll v;
while (ch-- && it--)
for (int i = 0; i < N; i++) if (pi[i] != INF)
for (edge& e : ed[i]) if (e.cap)
if ((v = pi[i] + e.cost) < pi[e.to])
pi[e.to] = v, ch = 1;
assert(it >= 0); // negative cost cycle
}
};
class UnionFind
{
private:
std::vector<int> root;
public:
UnionFind(size_t size)
{
root.resize(size);
for (size_t i = 0; i < size; i++)
{
root[i] = i;
}
}
int find(int x)
{
return root[x];
}
void unionSets(int x, int y)
{
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY)
{
for (size_t i = 0; i < root.size(); i++)
{
if (root[i] == rootY)
{
root[i] = rootX;
}
}
}
}
bool connected(int x, int y)
{
return find(x) == find(y);
}
int numSets()
{
unordered_set<int> uniqueRoots;
for (size_t i = 0; i < root.size(); i++)
{
uniqueRoots.insert(find(i));
}
return static_cast<int>(uniqueRoots.size());
}
};
class Graph
{
public:
struct Edge
{
int from;
int end;
ll weight;
Edge(int e, ll w)
: from(-1), end(e), weight(w)
{ }
Edge(int f, int e, ll w)
: from(f), end(e), weight(w)
{ }
};
private:
vector<size_t> head;
vector<int> to;
vector<ll> weight;
vector<size_t> next;
size_t n;
size_t idx = 1;
bool directed;
void check(int v) const
{
if (v < 0 || static_cast<size_t>(v) >= n)
{
throw out_of_range("vertex out of range");
}
}
void addOne(int s, int e, ll w)
{
if (idx >= to.size())
{
throw overflow_error("edge capacity exceeded");
}
to[idx] = e;
weight[idx] = w;
next[idx] = head[s];
head[s] = idx++;
}
public:
Graph(size_t size, bool isDirected = true)
: Graph(size, size * (size - 1), isDirected)
{ }
Graph(size_t size, size_t edgeCapacity, bool isDirected = true)
: head(size, 0),
to(edgeCapacity + 1),
weight(edgeCapacity + 1),
next(edgeCapacity + 1),
n(size),
directed(isDirected)
{
}
void add(int start, int end, ll w)
{
check(start);
check(end);
addOne(start, end, w);
if (!directed)
{
addOne(end, start, w);
}
}
bool isConnected(int start, int end) const
{
check(start);
check(end);
for (size_t i = head[start]; i; i = next[i])
{
if (to[i] == end)
{
return true;
}
}
return false;
}
vector<Edge> outEdges(int start) const
{
check(start);
vector<Edge> res;
for (size_t i = head[start]; i; i = next[i])
{
res.emplace_back(to[i], weight[i]);
}
return res;
}
size_t size() const
{
return n;
}
bool isDirected() const
{
return directed;
}
};
int main()
{
void solve();
#if defined(USACO) && !defined(LOCAL)
freopen(STR(USACO) ".in", "r", stdin);
freopen(STR(USACO) ".out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
solve();
return 0;
}
/*------------------------------------------------------------------------*/
void solve()
{
}