|
|
|
import java.util.*; |
|
|
|
class Edge{ |
|
String name; |
|
String revName; |
|
int capacity; |
|
int flow; |
|
int revFlow; |
|
int fromVertex; |
|
int toVertex; |
|
int residualCapacity; |
|
Edge(){} |
|
Edge(String n, int capN){ |
|
this.name = n; |
|
this.revName = reverseFlowName(); |
|
this.capacity = capN; |
|
this.flow = 0; |
|
this.revFlow = 0; |
|
this.fromVertex = fromVertex(); |
|
this.toVertex = toVertex(); |
|
this.residualCapacity = this.capacity - flow; |
|
} |
|
|
|
public int getResidualCapacity() { |
|
return residualCapacity; |
|
} |
|
|
|
public int getFromVertex() { |
|
return fromVertex; |
|
} |
|
|
|
public int getToVertex() { |
|
return toVertex; |
|
} |
|
|
|
int fromVertex(){ |
|
String[] frmArr = name.split(":"); |
|
int fvert = Integer.parseInt(frmArr[0]); |
|
|
|
return fvert; |
|
} |
|
|
|
int toVertex(){ |
|
String[] frmArr = name.split(":"); |
|
int tvert = Integer.parseInt(frmArr[1]); |
|
|
|
return tvert; |
|
} |
|
String reverseFlowName(){ |
|
char from = name.charAt(0); |
|
char to = name.charAt(1); |
|
String revName = Character.toString(to) + Character.toString(from); |
|
return revName; |
|
} |
|
public void updateResiCap(){ |
|
this.residualCapacity = this.capacity - this.flow; |
|
} |
|
public String getName() { |
|
return name; |
|
} |
|
|
|
public String getRevName() { |
|
return revName; |
|
} |
|
|
|
public void setCapacity(int capacity) { |
|
this.capacity = capacity; |
|
} |
|
|
|
public int getCapacity() { |
|
return capacity; |
|
} |
|
|
|
public int getFlow() { |
|
return flow; |
|
} |
|
|
|
public int getRevFlow() { |
|
return revFlow; |
|
} |
|
|
|
public void setFlow(int flow) { |
|
this.flow += flow; |
|
} |
|
|
|
public void setRevFlow(int revFlow) { |
|
this.revFlow = revFlow; |
|
} |
|
|
|
} |
|
class Vertex{ |
|
int name; |
|
int distance; |
|
int parent; |
|
boolean visited; |
|
|
|
Vertex(int n){ |
|
this.name = n; |
|
this.distance = -1; |
|
this.parent = -1; |
|
this.visited = false; |
|
} |
|
|
|
public boolean isVisited() { |
|
return visited; |
|
} |
|
|
|
public void setVisited(boolean visited) { |
|
this.visited = visited; |
|
} |
|
|
|
public int getName() { |
|
return name; |
|
} |
|
|
|
public int getDistance() { |
|
return distance; |
|
} |
|
|
|
public int getParent() { |
|
return parent; |
|
} |
|
|
|
public void setDistance(int distance) { |
|
this.distance = distance; |
|
} |
|
|
|
public void setParent(int parent) { |
|
this.parent = parent; |
|
} |
|
|
|
} |
|
|
|
class BFS{ |
|
|
|
TreeMap<Integer, LinkedList<Integer>> adjList = new TreeMap<Integer, LinkedList<Integer>>(); |
|
ArrayList<Edge> path = new ArrayList<Edge>(); |
|
BFS(){} |
|
public boolean doBFS(ArrayList<Vertex> vert, ArrayList<Edge> edges, int[] parent){ |
|
for(int i = 1; i<=vert.size(); i++){ |
|
adjList.put(i, new LinkedList<Integer>()); |
|
} |
|
for(Edge x : edges){ |
|
if(adjList.containsKey(x.getFromVertex())){ |
|
adjList.get(x.getFromVertex()).add(x.toVertex()); |
|
}else{ |
|
LinkedList<Integer> ll = new LinkedList<Integer>(); |
|
adjList.put(x.getFromVertex(), ll); |
|
|
|
adjList.get(x.getFromVertex()).add(x.toVertex()); |
|
} |
|
|
|
} |
|
// System.out.println(adjList.toString()); |
|
int[] visited = new int[vert.size()+1]; |
|
|
|
Queue<Integer> q = new LinkedList<Integer>(); |
|
parent[1] = -1; |
|
vert.get(0).setDistance(0); |
|
q.add(vert.get(0).getName()); |
|
// System.out.println(vert.get(0).getName()); |
|
|
|
while(!q.isEmpty()){ |
|
int u = q.remove(); |
|
//System.out.println(u); |
|
Iterator<Integer> itr = adjList.get(u).iterator(); |
|
while(itr.hasNext()){ |
|
int v = itr.next(); |
|
//System.out.println("v " + v); |
|
for(Edge e : edges){ |
|
if(e.getFromVertex() == u && e.toVertex() == v ){ |
|
if(e.getCapacity()>0 && visited[v] == 0){ |
|
q.add(v); |
|
visited[v] = 1; |
|
parent[v] = u; |
|
} |
|
} |
|
} |
|
|
|
} |
|
} |
|
return (visited[vert.size()] ==1); |
|
} |
|
} |
|
|
|
public class MaxFlowPlumbing { |
|
public static void main(String[] args) { |
|
ArrayList<Vertex> vertxList = new ArrayList<Vertex>(); |
|
ArrayList<Edge> edgeList = new ArrayList<Edge>(); |
|
ArrayList<Integer> path = new ArrayList<Integer>(); |
|
Scanner input = new Scanner(System.in); |
|
int maxCapacity = 0; |
|
int maxFlow = 0; |
|
int noOfVertex = input.nextInt(); |
|
int noOfEdges = input.nextInt(); |
|
int lastVertex = noOfVertex; |
|
|
|
for(int i = 1; i <= noOfVertex; i++){ |
|
Vertex newVert = new Vertex(i); |
|
vertxList.add(newVert); |
|
} |
|
|
|
for(int i = 0; i < noOfEdges; i++){ |
|
String from = input.next(); |
|
String to = input.next(); |
|
int capacity = input.nextInt(); |
|
if(Integer.parseInt(to) == lastVertex){ |
|
maxCapacity += capacity; |
|
} |
|
String edgeName = from +":"+ to; |
|
Edge newEdge = new Edge(edgeName, capacity); |
|
edgeList.add(newEdge); |
|
|
|
} |
|
int[] parent = new int[vertxList.size()+1]; |
|
BFS getPath = new BFS(); |
|
|
|
while(getPath.doBFS(vertxList, edgeList, parent)){ |
|
int flow = 1000000; |
|
for(int i = vertxList.size(); i !=1 ; i = parent[i]){ |
|
int u = parent[i]; |
|
for(Edge x : edgeList){ |
|
if(x.getFromVertex() == u && x.getToVertex() == i){ |
|
if(x.getCapacity()<flow){ |
|
flow = x.getCapacity(); |
|
} |
|
} |
|
} |
|
} |
|
for(int j = vertxList.size(); j!=1; j=parent[j]){ |
|
int u = parent[j]; |
|
boolean flag = false; |
|
for(Edge x: edgeList){ |
|
if(x.getFromVertex()== u && x.toVertex() == j){ |
|
x.setCapacity(x.getCapacity()-flow); |
|
} |
|
} |
|
for(Edge y: edgeList){ |
|
if (y.getFromVertex()== j && y.toVertex() == u){ |
|
y.setCapacity(y.getCapacity()+flow); |
|
flag = true; |
|
break; |
|
} |
|
} |
|
if(!flag){ |
|
edgeList.add(new Edge(Integer.toString(j)+":"+Integer.toString(u), flow)); |
|
} |
|
} |
|
|
|
maxFlow += flow; |
|
} |
|
|
|
if(maxFlow<maxCapacity){ |
|
System.out.println("Yes"); |
|
}else{ |
|
System.out.println("No"); |
|
} |
|
|
|
System.out.println(maxFlow); |
|
|
|
} |
|
} |