#include <bits/stdc++.h>
using namespace std;
// ===================================================================
// This file contains a collection of Dinic (Maximum Flow) algorithms.
// Each function/class 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
// - Explanation of common terms (Jargon) to make it easy for beginners.
// ===================================================================
// ===================================================================
// JARGON / TERMINOLOGY EXPLANATION (Read this first!)
// ===================================================================
// 1. Flow Network: A directed graph where each edge has a "capacity"
// (maximum amount it can carry). We send "flow" (like water or data)
// from a "Source" (starting point) to a "Sink" (ending point).
//
// 2. Source (s): The node where the flow originates.
// 3. Sink (t): The node where the flow ends.
// 4. Capacity (cap): The maximum amount of flow that can pass through an edge.
// 5. Reverse Edge (Residual Edge): An artificial edge added by the algorithm
// that allows it to "undo" or reroute flow if a better path is found later.
// 6. Residual Graph: The original graph plus all the reverse edges.
// 7. Level Graph (BFS Layers): A simplified graph where we only keep edges
// that go from a node in the current BFS layer to the next layer.
// This helps the algorithm find the shortest augmenting paths.
// 8. Blocking Flow: Sending as much flow as possible through the current
// Level Graph before rebuilding it.
// 9. Current Arc Optimization: A trick that remembers which edges have
// already been completely used (saturated) in the current blocking flow,
// so we don't waste time checking them again.
// 10. Min Cut: The minimum total capacity of edges we need to remove to
// completely disconnect the Source from the Sink.
// 11. Saturated Edge: An edge where the remaining capacity (cap) is zero.
// ===================================================================
// ===================================================================
// MAIN DINIC CLASS (The core engine)
// ===================================================================
// What it solves:
// Computes the Maximum Flow in a directed graph.
//
// Input:
// - Number of nodes (n) in the graph (nodes are 0-indexed).
//
// How to use:
// 1. Create an object: Dinic dinic(number_of_nodes);
// 2. Add edges using addEdge(u, v, capacity).
// 3. Call maxFlow(source, sink) to get the maximum flow value.
//
// Time Complexity:
// O(E * V^2) in the worst case for general graphs.
// In practice, it is very fast, especially on sparse graphs.
// For Bipartite Matching, it runs in O(E * sqrt(V)).
// NOTE: The "current arc optimization" speeds it up significantly.
//
// Notes:
// - All capacities and flows are stored as 'long long' to prevent overflow.
// - If you have an undirected edge, you should call addUndirectedEdge
// (provided in the Tricks section), or add two directed edges.
// - The graph is 0-indexed. If your nodes are 1-indexed, subtract 1 from
// every node index.
// ===================================================================
struct Dinic {
struct Edge {
int to; // The node this edge goes to
int rev; // Index of the reverse edge in the adjacency list of 'to'
long long cap; // Remaining capacity of this edge
};
int n; // Number of nodes
vector<vector<Edge>> adj; // Adjacency list
vector<int> level; // BFS level of each node
vector<int> it; // Pointer for current arc optimization
// Constructor: initializes the graph with 'n' nodes.
Dinic(int n) : n(n), adj(n), level(n), it(n) {}
// -----------------------------------------------------------------
// addEdge
// -----------------------------------------------------------------
// What it does:
// Adds a directed edge from node 'u' to node 'v' with a maximum
// capacity 'cap'. Flow can only travel from 'u' to 'v' in the
// original network.
//
// Input:
// u : source node of the edge
// v : destination node of the edge
// cap : maximum capacity of this edge (must be >= 0)
//
// Output:
// None (modifies the graph internally).
//
// Time complexity:
// O(1)
//
// Notes:
// - This automatically adds a reverse edge (with 0 capacity) for
// the algorithm to work. You should NOT manually modify or call
// this reverse edge directly.
// - If cap == 0, the edge is useless but can be safely added.
// -----------------------------------------------------------------
void addEdge(int u, int v, long long 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);
}
// -----------------------------------------------------------------
// bfs (Breadth First Search) - Internal helper
// -----------------------------------------------------------------
// What it does:
// Constructs the "Level Graph" by calculating the shortest distance
// (in terms of number of edges) from the source to every other node
// using only edges that still have remaining capacity (> 0).
//
// Input:
// s : the source node
// t : the sink node (not strictly needed for BFS, but we stop early if we reach it)
//
// Output:
// Returns 'true' if the sink 't' is reachable from 's', 'false' otherwise.
//
// Time complexity:
// O(V + E)
//
// Notes:
// You don't need to call this manually; it is called inside maxFlow().
// -----------------------------------------------------------------
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 (const Edge& e : adj[u]) {
if (e.cap > 0 && level[e.to] == -1) {
level[e.to] = level[u] + 1;
if (e.to == t) {
// We don't return immediately here to allow full leveling,
// but returning early is also safe. We keep standard BFS.
}
q.push(e.to);
}
}
}
return level[t] != -1;
}
// -----------------------------------------------------------------
// dfs (Depth First Search) - Internal helper
// -----------------------------------------------------------------
// What it does:
// Sends as much flow as possible from node 'u' to the sink 't'
// using the current Level Graph. It only uses edges that go from
// the current BFS layer to the next BFS layer (level[v] == level[u] + 1).
//
// Input:
// u : current node
// t : sink node
// f : maximum amount of flow we are allowed to push through this path
//
// Output:
// Returns the amount of flow actually pushed to the sink.
//
// Time complexity:
// O(E) per DFS call, but with current arc optimization, total is O(E * V).
//
// Notes:
// - This is called repeatedly by maxFlow().
// - "Current Arc" optimization is implemented using the 'it' pointer.
// It remembers which edges are already saturated so we skip them.
// -----------------------------------------------------------------
long long dfs(int u, int t, long long f) {
if (u == t) return f;
for (int &i = it[u]; i < (int)adj[u].size(); i++) {
Edge &e = adj[u][i];
if (e.cap > 0 && level[e.to] == level[u] + 1) {
long long pushed = dfs(e.to, t, min(f, e.cap));
if (pushed > 0) {
e.cap -= pushed;
adj[e.to][e.rev].cap += pushed;
return pushed;
}
}
}
return 0;
}
// -----------------------------------------------------------------
// maxFlow
// -----------------------------------------------------------------
// What it solves:
// Computes the maximum amount of flow that can be sent from the
// 'source' node to the 'sink' node in the network.
//
// Input:
// s : the source node index
// t : the sink node index
//
// Output:
// Returns the total maximum flow value (long long).
//
// Time complexity:
// O(E * V^2) in the worst case.
//
// Constraints:
// - Source and sink must be different nodes (s != t).
// - All capacities must be non-negative.
//
// Notes:
// - After this function finishes, the graph will contain the residual
// graph. The remaining capacities in the 'adj' list represent
// the residual capacities.
// -----------------------------------------------------------------
long long maxFlow(int s, int t) {
long long flow = 0;
const long long INF = 4e18; // A very large number
while (bfs(s, t)) {
fill(it.begin(), it.end(), 0);
while (true) {
long long pushed = dfs(s, t, INF);
if (pushed == 0) break;
flow += pushed;
}
}
return flow;
}
// -----------------------------------------------------------------
// getReachableNodes (For Min Cut)
// -----------------------------------------------------------------
// What it solves:
// After computing the maximum flow, this function finds all nodes
// that are still reachable from the 'source' in the residual graph.
// The set of these nodes defines the "Source Side" of the minimum cut.
//
// Input:
// s : the source node index
//
// Output:
// Returns a vector of booleans (size = n) where 'true' means the node
// is reachable from the source in the residual graph.
//
// Time complexity:
// O(V + E)
//
// How to find the Min Cut edges:
// Iterate over all original edges (u->v). If reachable[u] is true
// and reachable[v] is false, then this edge is part of the minimum cut.
//
// Constraints:
// - Must be called AFTER running maxFlow(s, t).
// -----------------------------------------------------------------
vector<bool> getReachableNodes(int s) {
vector<bool> reachable(n, false);
queue<int> q;
q.push(s);
reachable[s] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
for (const Edge& e : adj[u]) {
if (e.cap > 0 && !reachable[e.to]) {
reachable[e.to] = true;
q.push(e.to);
}
}
}
return reachable;
}
};
// ===================================================================
// 1) BIPARTITE MATCHING (Using Max Flow)
// ===================================================================
// What it solves:
// Given two disjoint sets of nodes (Left and Right), and allowed
// connections between them, find the maximum number of pairs
// (one from Left, one from Right) such that each node is used at most once.
// Example: Assigning workers to jobs.
//
// Input:
// - n: number of nodes on the Left side (indexed 0..n-1)
// - m: number of nodes on the Right side (indexed 0..m-1)
// - edges: a vector of pairs (u, v) meaning Left-node 'u' can connect to Right-node 'v'.
//
// Output:
// - Returns the maximum number of matches (pairs).
// - If you need the actual matching pairs, you would need to trace the flow
// (this function only returns the count).
//
// Time complexity:
// O(E * sqrt(V)) because Dinic on bipartite graphs is very fast.
// Where V = n + m + 2 (plus source and sink), E = number of edges.
//
// Constraints:
// - n, m >= 0.
// - Node indices must be in the valid ranges.
//
// Notes:
// - This function builds the flow network internally.
// - The source is connected to all Left nodes (capacity 1).
// - Left nodes connect to Right nodes (capacity 1).
// - Right nodes connect to the sink (capacity 1).
// -----------------------------------------------------------------
int maxBipartiteMatching(int n, int m, const vector<pair<int, int>>& edges) {
int totalNodes = n + m + 2;
int source = n + m;
int sink = source + 1;
Dinic dinic(totalNodes);
// Connect source to left nodes
for (int u = 0; u < n; u++) {
dinic.addEdge(source, u, 1);
}
// Connect left to right
for (auto [u, v] : edges) {
// Right nodes are offset by n to avoid index collision with left nodes
dinic.addEdge(u, n + v, 1);
}
// Connect right nodes to sink
for (int v = 0; v < m; v++) {
dinic.addEdge(n + v, sink, 1);
}
long long flow = dinic.maxFlow(source, sink);
return (int)flow;
}
// ===================================================================
// 2) MINIMUM PATH COVER IN A DAG (Using Max Flow)
// ===================================================================
// What it solves:
// Given a Directed Acyclic Graph (DAG), find the minimum number of
// vertex-disjoint paths needed to cover all vertices.
// Each vertex belongs to exactly one path.
//
// Input:
// - n: number of vertices (0-indexed).
// - edges: a vector of pairs (u, v) representing a directed edge u -> v.
//
// Output:
// - Returns the minimum number of paths required to cover all nodes.
//
// Time complexity:
// O(E * sqrt(V)) using Dinic.
//
// Constraint:
// - The graph must be a DAG (no cycles). If there are cycles, the
// mathematical reduction doesn't hold.
// - Paths are vertex-disjoint (no vertex appears in more than one path).
//
// Idea (explained simply):
// The minimum path cover equals (Total Vertices) - (Maximum Bipartite Matching).
// We create a bipartite graph where the left side contains all original nodes,
// and the right side contains copies of all original nodes.
// For every edge u -> v in the DAG, we add an edge from Left(u) to Right(v).
// Running max matching gives the maximum number of edges we can "chain"
// together, which reduces the number of paths.
// -----------------------------------------------------------------
int minPathCoverDAG(int n, const vector<pair<int, int>>& edges) {
// Build the bipartite graph (Left: 0..n-1, Right: 0..n-1)
// We reuse the bipartite matching function.
vector<pair<int, int>> bipEdges;
for (auto [u, v] : edges) {
bipEdges.push_back({u, v}); // Left side u, Right side v (both use same indices)
}
int maxMatch = maxBipartiteMatching(n, n, bipEdges);
return n - maxMatch;
}
// ===================================================================
// TRICKS & ADVANCED PATTERNS (ECPC/ACPC Favorites)
// ===================================================================
// 3.1) SUPER SOURCE AND SUPER SINK
// -----------------------------------------------------------------
// What it solves:
// When you have multiple sources or multiple sinks, you can connect
// all sources to a single "Super Source" (with INFINITE capacity), and
// connect all sinks to a single "Super Sink" (with INFINITE capacity).
//
// How to use (Example):
// int N = ...; int S = N; int T = N+1; // create two new nodes
// Dinic dinic(N+2);
// for source in list_of_sources: dinic.addEdge(S, source, INF);
// for sink in list_of_sinks: dinic.addEdge(sink, T, INF);
// // Add your normal edges here...
// long long ans = dinic.maxFlow(S, T);
//
// Input:
// - You don't call a function for this; it's a pattern.
// - Just add edges from SuperSource to all sources, and all sinks to SuperSink.
//
// Output:
// - The result of maxFlow(SuperSource, SuperSink) is the answer.
//
// Notes:
// - Use INF = 4e18 (or a very large number bigger than any possible flow).
// -----------------------------------------------------------------
// 3.2) NODE SPLITTING (Vertex Capacities)
// -----------------------------------------------------------------
// What it solves:
// By default, only edges have capacities. If you need to limit the
// amount of flow that passes THROUGH a specific node, you must split it.
//
// How to use (Example):
// For a node 'v' with capacity 'cap', split it into two nodes:
// v_in = v * 2, and v_out = v * 2 + 1 (or any other indexing scheme).
// Add an edge: addEdge(v_in, v_out, cap).
// For any incoming edge (u -> v), add u_out -> v_in.
// For any outgoing edge (v -> w), add v_out -> w_in.
//
// Input:
// - You don't call a function for this; it's a pattern.
//
// Notes:
// - Make sure to allocate enough nodes (2 * number_of_original_nodes).
// -----------------------------------------------------------------
// 3.3) MAXIMUM WEIGHT CLOSURE (Min Cut Application)
// -----------------------------------------------------------------
// What it solves:
// You have a set of projects (nodes). Each project gives a certain profit
// (can be positive or negative). There are dependencies: to take project A,
// you must take project B. Find the maximum total profit you can achieve.
//
// Idea (simplified):
// - Positive profit projects are connected from Source with capacity = profit.
// - Negative profit projects are connected to Sink with capacity = -profit.
// - Dependencies (A depends on B) are added as edges (A -> B) with INF capacity.
// - Answer = (Sum of all positive profits) - maxFlow(Source, Sink).
//
// Input:
// - n: number of projects.
// - profits: vector of long long (size n), where profits[i] is the profit (can be negative).
// - deps: vector of pairs (a, b) meaning "if you take 'a', you must take 'b'".
//
// Output:
// - Returns the maximum achievable total profit.
//
// Time complexity:
// O(maxFlow) on a graph with n+2 nodes.
//
// Notes:
// - This is a classic problem in competitive programming.
// - If you don't understand the math, just follow the pattern.
// -----------------------------------------------------------------
long long maxWeightClosure(int n, const vector<long long>& profits, const vector<pair<int, int>>& deps) {
int S = n;
int T = n + 1;
Dinic dinic(n + 2);
long long totalPositive = 0;
const long long INF = 4e18;
for (int i = 0; i < n; i++) {
if (profits[i] > 0) {
dinic.addEdge(S, i, profits[i]);
totalPositive += profits[i];
} else if (profits[i] < 0) {
dinic.addEdge(i, T, -profits[i]); // capacity is positive
}
}
for (auto [a, b] : deps) {
// If we take 'a', we must take 'b'.
// Edge a -> b with INF capacity means cutting this edge is too expensive,
// so the min cut won't separate a (source side) from b (sink side)
// unless b is cut off from the source.
dinic.addEdge(a, b, INF);
}
long long minCut = dinic.maxFlow(S, T);
return totalPositive - minCut;
}
// 3.4) FLOW WITH LOWER BOUNDS (Feasible Flow / Circulation)
// -----------------------------------------------------------------
// What it solves:
// Sometimes, edges don't just have a maximum capacity, but also a
// MINIMUM required flow (lower bound). We need to check if it's
// possible to send flow satisfying all lower and upper bounds.
// This function can handle both pure circulation (no source/sink)
// and standard s‑t flow with lower bounds.
//
// Input:
// - n: number of nodes.
// - edges: a vector of LowerBoundEdge (u, v, lower, upper).
// Means: edge from u to v must carry at least 'lower' and at most 'upper' flow.
// - s: (optional) source node for s‑t flow. Use -1 for circulation (default).
// - t: (optional) sink node for s‑t flow. Use -1 for circulation (default).
//
// Output:
// - Returns 'true' if a feasible flow exists, 'false' otherwise.
// - If 'true', the residual graph will contain the solution (flow values
// can be recovered if needed).
//
// Time complexity:
// O(maxFlow) on a graph with n+2 nodes and E edges.
//
// How it works (simplified):
// 1. Create a new graph with a Super Source (SS) and Super Sink (TT).
// 2. For each edge (u->v) with [L, U]:
// - Add edge (u -> v) with capacity (U - L). (The adjustable part).
// - Store the demand: demand[u] -= L; demand[v] += L.
// 3. After processing all edges, for each node i:
// - If demand[i] > 0: add edge (SS -> i) with capacity demand[i].
// - If demand[i] < 0: add edge (i -> TT) with capacity -demand[i].
// 4. If s and t are given (not -1), add an edge (t -> s) with INF capacity
// to convert the problem into a circulation.
// 5. Run maxFlow(SS, TT). If the flow equals the sum of positive demands,
// then a feasible solution exists.
//
// Constraints:
// - 0 <= lower <= upper.
// - Nodes are 0-indexed.
// - If s and t are provided, they must be valid nodes and different.
//
// Notes:
// - This function does NOT return the actual flow values on edges,
// but the residual graph can be used to reconstruct them.
// - For pure circulation, call with s = -1, t = -1 (or omit the parameters).
// -----------------------------------------------------------------
struct LowerBoundEdge {
int u, v;
long long lower, upper;
};
bool feasibleFlowWithLowerBounds(int n, const vector<LowerBoundEdge>& edges, int s = -1, int t = -1) {
int SS = n;
int TT = n + 1;
Dinic dinic(n + 2);
vector<long long> demand(n, 0);
const long long INF = 4e18;
for (const auto& e : edges) {
demand[e.u] -= e.lower;
demand[e.v] += e.lower;
dinic.addEdge(e.u, e.v, e.upper - e.lower);
}
long long totalPositiveDemand = 0;
for (int i = 0; i < n; i++) {
if (demand[i] > 0) {
dinic.addEdge(SS, i, demand[i]);
totalPositiveDemand += demand[i];
} else if (demand[i] < 0) {
dinic.addEdge(i, TT, -demand[i]);
}
}
// If we have a specific source and sink, add an infinite edge from sink to source
// to make it a circulation problem.
if (s != -1 && t != -1) {
dinic.addEdge(t, s, INF);
}
long long maxflow = dinic.maxFlow(SS, TT);
return maxflow == totalPositiveDemand;
}
// ===================================================================
// 4) MISCELLANEOUS UTILITY WRAPPERS
// ===================================================================
// 4.1) addUndirectedEdge
// -----------------------------------------------------------------
// What it solves:
// Adds an undirected edge between 'u' and 'v' with capacity 'cap'.
// This means flow can go from u to v up to cap, and from v to u up to cap,
// but the net flow (u->v minus v->u) cannot exceed cap in magnitude.
// (i.e., the total flow crossing the edge in either direction is bounded by cap).
//
// Input:
// u, v : the two nodes
// cap : the maximum net capacity in either direction.
//
// How to use:
// dinic.addUndirectedEdge(u, v, cap);
//
// Notes:
// Internally, it adds two directed edges each with capacity 'cap'.
// This correctly models an undirected edge because positive flow in one
// direction cancels negative flow in the other direction in the residual graph.
// If you need independent capacities (u->v with cap1, v->u with cap2),
// just call addEdge(u, v, cap1) and addEdge(v, u, cap2) separately.
// -----------------------------------------------------------------
void addUndirectedEdge(Dinic& dinic, int u, int v, long long cap) {
dinic.addEdge(u, v, cap);
dinic.addEdge(v, u, cap);
}
// 4.2) getMinCutEdges (Helper)
// -----------------------------------------------------------------
// What it solves:
// Given a Dinic graph after running maxFlow, and the reachable nodes,
// it returns a vector of the original edges that form the minimum cut.
//
// Input:
// - dinic: the Dinic object (must have run maxFlow() already).
// - reachable: the boolean vector from dinic.getReachableNodes(source).
// - originalEdges: a vector of the original directed edges that were added.
// (You need to store them when you call addEdge if you want to extract them).
//
// Output:
// - vector of pairs (u, v) representing the edges in the min cut.
//
// Note:
// Since we don't store the original edges in the class by default,
// this is just a demonstration pattern.
// -----------------------------------------------------------------
// vector<pair<int, int>> getMinCutEdges(Dinic& dinic, vector<bool>& reachable) {
// vector<pair<int, int>> cutEdges;
// for (int u = 0; u < dinic.n; u++) {
// if (!reachable[u]) continue;
// for (const auto& e : dinic.adj[u]) {
// // We need to know if 'e' is a forward edge.
// // Since we don't track that, it's easier to store the original edges list.
// // Just iterate over your stored original edges and check
// // reachable[edge.u] && !reachable[edge.v].
// }
// }
// return cutEdges;
// }
// ===================================================================
// main() with example usage (Black-box testing)
// ===================================================================
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Example 1: Simple Max Flow
// Nodes: 0, 1, 2, 3. Source = 0, Sink = 3.
// Edges: 0->1 (10), 0->2 (10), 1->3 (10), 2->3 (10), 1->2 (5).
cout << "=== Example 1: Simple Max Flow ===\n";
{
Dinic dinic(4);
dinic.addEdge(0, 1, 10);
dinic.addEdge(0, 2, 10);
dinic.addEdge(1, 3, 10);
dinic.addEdge(2, 3, 10);
dinic.addEdge(1, 2, 5);
long long flow = dinic.maxFlow(0, 3);
cout << "Max Flow: " << flow << "\n"; // Expected: 20 (Path 0-1-3 and 0-2-3)
}
// Example 2: Bipartite Matching
// Left: 0, 1. Right: 0, 1.
// Edges: (0,0), (0,1), (1,0).
cout << "\n=== Example 2: Bipartite Matching ===\n";
{
vector<pair<int, int>> edges = {{0, 0}, {0, 1}, {1, 0}};
int matches = maxBipartiteMatching(2, 2, edges);
cout << "Max Matches: " << matches << "\n"; // Expected: 2
}
// Example 3: Max Weight Closure
// Projects: A(profit 10), B(profit -5), C(profit 6).
// Dependencies: A depends on B, C depends on B.
cout << "\n=== Example 3: Max Weight Closure ===\n";
{
vector<long long> profits = {10, -5, 6};
vector<pair<int, int>> deps = {{0, 1}, {2, 1}}; // 0->1, 2->1
long long maxProfit = maxWeightClosure(3, profits, deps);
cout << "Max Profit: " << maxProfit << "\n"; // Expected: 11 (Take A, B, C. Sum=11)
}
// Example 4: Feasible Flow with Lower Bounds (Circulation)
cout << "\n=== Example 4: Feasible Flow with Lower Bounds (Circulation) ===\n";
{
// Nodes: 0, 1, 2.
// Edge 0->1: lower=5, upper=10
// Edge 1->2: lower=5, upper=10
// Edge 2->0: lower=5, upper=10 (to make a circulation)
vector<LowerBoundEdge> edges = {
{0, 1, 5, 10},
{1, 2, 5, 10},
{2, 0, 5, 10}
};
bool feasible = feasibleFlowWithLowerBounds(3, edges); // circulation
cout << "Feasible: " << (feasible ? "Yes" : "No") << "\n"; // Expected: Yes
}
// Example 5: Feasible Flow with Lower Bounds (s-t flow)
cout << "\n=== Example 5: Feasible Flow with Lower Bounds (s-t) ===\n";
{
// Nodes: 0,1,2. Source=0, Sink=2.
// Edge 0->1: lower=2, upper=5
// Edge 1->2: lower=3, upper=6
// Also need an edge 2->0 with lower=0, upper=INF to make circulation? Actually for s-t,
// we add the infinite edge automatically when we pass s and t.
vector<LowerBoundEdge> edges = {
{0, 1, 2, 5},
{1, 2, 3, 6}
};
bool feasible = feasibleFlowWithLowerBounds(3, edges, 0, 2);
cout << "Feasible: " << (feasible ? "Yes" : "No") << "\n"; // Expected: Yes (can send 3-5 flow)
}
return 0;
}