import java.io.PrintStream; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * Solution to Room Evacuation using Ford/Fulkerson. * * @author vanb */ public class room_vanb_ff { /** Input. */ private static Scanner sc; /** Output. */ private static PrintStream ps; /** * A node of a max flow graph. * * @author vanb */ private class Node { /** Has the node been visited?. */ public boolean visited = false; /** List of edges out from this node. */ public ArrayList edges = new ArrayList(); /** If this node has been visited, what edge did we get here from?. */ public Edge gothere = null; } /** * An edge of a max flow graph. * * @author vanb */ private class Edge { /** The destination. */ Node destination; /** The capacity. */ int capacity; /** The dual. */ Edge dual; /** * Instantiates a new edge. * * @param d the Destination Node * @param c the Capacity */ public Edge( Node d, int c ) { capacity = c; destination = d; dual = null; } } /** * Create a link between two nodes of a max flow graph. * * @param n1 From node * @param n2 To node * @param cost Cost to go from n1 to n2 */ private void link( Node n1, Node n2, int cost ) { Edge e12 = new Edge( n2, cost ); Edge e21 = new Edge( n1, 0 ); e12.dual = e21; e21.dual = e12; n1.edges.add( e12 ); n2.edges.add( e21 ); } /** The room. */ private char room[][]; /** The size of the room. */ private int n, m; /** * Can a person go to room[i][j]? * * @param i the i * @param j the j * @return true, if room[i][j] exists and can be occupied. */ private boolean cango( int i, int j ) { return i>=0 && i=0 && j nodes ) { int total = 0; ArrayDeque queue = new ArrayDeque(nodes.size()); // Keep going until you can't get from the source to the sink for(;;) { // Reset the graph for( Node node : nodes ) node.visited = false; // Reset the queue // Start at the source queue.clear(); queue.add( src ); src.visited = true; // Have we found the sink? boolean found = false; // Use a breadth-first search to find a path from the source to the sink while( queue.size()>0 ) { Node node = queue.poll(); // Have we found the sink? If so, break out of the BFS. if( node==snk ) { found = true; break; } // Look for edges to traverse for( Edge edge : node.edges ) { Node dest = edge.destination; // If this destination hasn't been visited, // and the edge has capacity, // put it on the queue. if( edge.capacity>0 && !dest.visited ) { // Add to the queue dest.visited = true; dest.gothere = edge; queue.add( dest ); } } } // If we were unable to get to the sink, then we're done if( !found ) break; // Add that flow to the total ++total; // Go back along the path, and for each edge, move // the flow from the edge to its dual. for( Node node = snk; node.gothere != null; ) { Edge edge = node.gothere; --edge.capacity; ++edge.dual.capacity; node = edge.dual.destination; } } // Return the total return total; } /** * Do it!. */ private void doit() { n = sc.nextInt(); m = sc.nextInt(); int t = sc.nextInt()+1; room = new char[n][]; // Read the room for( int i=0; i nodes = new ArrayList(n*m*t+2); Node source = new Node(); Node sink = new Node(); nodes.add( source ); nodes.add( sink ); // Create the nodes Node graph[][][] = new Node[n][m][t]; for( int i=0; i