活跃农民
- 积分
- 305
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2015-7-16
- 最后登录
- 1970-1-1
|
- import java.util.*;
- public class QuoraStackingBox {
- public static void main(String[] args){
- // Scanner scan = new Scanner(System.in);
- // int n = 0;
- // if(scan.hasNextInt()){
- // n = scan.nextInt();
- // }
- // int[][] input = new int[n][2];
- // for(int i = 0; i < n; i++){
- // if(scan.hasNextInt()){
- // input[i][0] = scan.nextInt();
- // }
- // if(scan.hasNextInt()){
- // input[i][1] = scan.nextInt();
- // }
- // }
- // System.out.println("");
- QuoraStackingBox solution = new QuoraStackingBox();
- int[][] input = new int[][]{{9,4}, {6,9}, {6,9}, {6,4}, {1,1}};//{2,5},{3,3},{6,6},{7,8}};//,{1,10},{1,1},{1,1},{1,1}};
- // int[][] input = null;
- // int[][] input = new int[][]{};
- // System.out.println(solution.stackingBox(input));
- // test constructDirectedGraph() PASS!
- // int[][] res = solution.constructDirectedGraph(input);
- // for(int i = 0; i < res.length; i++){
- // for(int j = 0; j < res.length; j++){
- // System.out.print(res[i][j]);
- // }
- // System.out.println();
- // }
- System.out.println(solution.stackingBox(input));
-
- }
- public int stackingBox(int[][] box){
- if(box == null || box.length == 0){
- return 0;
- }
- int[][] graph = constructDirectedGraph(box);
- int s = graph.length - 2;
- int t = graph.length - 1;
- return fordFulkerson(graph, s, t);
- }
-
- //bfs all vertices, if there is a path from source "s" to sink "t" in the residual graph
- //return true; Also the function fills "parentPath[]" to store the path
- public boolean bfs(int graph[][], int s, int t, int[] parentPath){
- //visited array to used to mark the vertices that has been visited
- //if visited: true, else: false
- boolean[] visited = new boolean[graph.length];
- //create a queue, enqueue source vertex and mark it as visited
- Deque<Integer> queue = new LinkedList<Integer>();
- queue.offer(s);
- visited[s] = true;
- parentPath[s]=-1;
- //Standard BFS Loop
- while(!queue.isEmpty()){
- int curr = queue.poll();
- for(int i = 0; i < graph.length; i++){
- if(visited[i] || graph[curr][i] == 0){
- continue;
- }
- queue.offer(i);
- parentPath[i] = curr;
- visited[i] = true;
- }
- }
- //if sink "t" has been visited, which means we have reached "t" in
- //BFS starting from source, then we return true; else, return false.
- return visited[t] == true;
- }
- //Ford Fulkerson algorithm to find Max Flow
- //return the maximum flow value from s to t in the given graph
- int fordFulkerson(int[][] graph, int s, int t)
- {
- int[][] residualGraph = new int[graph.length][graph.length];
- for(int i = 0; i < graph.length; i++){
- for(int j = 0; j < graph.length; j++){
- residualGraph[i][j] = graph[i][j];
- }
- }
- int maxFlow = 0;
- int parentPath[] = new int[graph.length];
- //test
-
- while(bfs(residualGraph, s, t, parentPath)){
- //Find minimum residual capacity(min_capacity) of the edges along the path filled by BFS
- //min_capacity is also the max_Flow on this path
- int min_capacity = Integer.MAX_VALUE;
- int v = t;
- while(parentPath[v] != s){
- int u = parentPath[v];
- min_capacity = Math.min(min_capacity, residualGraph[u][v]);
- v = u;
- }
- //update Residual Graph
- int vv = t;
- while(parentPath[vv] != s){
- int u = parentPath[vv];
- residualGraph[u][vv] -= min_capacity;
- residualGraph[vv][u] += min_capacity;
- vv = u;
- }
- //add path flow to overall flow
- maxFlow += min_capacity;
- }
- //return overall flow/ Max Flow
- return maxFlow;
- }
-
- public int[][] constructDirectedGraph(int[][] box){
- //box.length is the number of box
- //graph[i][j] means the capacity from i to j: could be used to check "if it has out-going arrow"
- int[][] graph = new int[box.length][box.length];
- //counterGraph[i][j] means the capacity from j to i: : could be used to check "if it has in-going arrow"
- int[][] counterGraph = new int[box.length][box.length];
- for(int i = 0; i < box.length; i++){
- for(int j = 0; j < box.length; j++){
- //Then j is bigger than i, j=>i
- //no need to judge whether it should point to himself
- if(j == i){
- continue;
- }
- if(box[j][0] < box[i][0] && box[j][1] < box[i][1]){
- counterGraph[i][j] = 1;
- }
- if(box[j][0] > box[i][0] && box[j][1] > box[i][1]){
- graph[i][j] = 1;
- }
- }
- }
- //add s and t: s: superGraph[box.length] || t: superGraph[box.length + 1]
- //superGraph[i][j] means the capacity from i to j
- int[][] superGraph = new int[box.length + 2][box.length + 2];
- for(int i = 0; i < box.length; i++){
- boolean nothingEnter = true;//nothingEnter
- boolean nothingOut = true;//nothingOut
- for(int j = 0; j < box.length; j++){
- if(graph[i][j] > 0){
- nothingOut = false;//it could reach others, so it can not be t
- }
- if(counterGraph[i][j] > 0){
- nothingEnter = false;//it can be reached by others, so it can not be s
- }
- }
-
- if(nothingEnter && nothingOut){
- superGraph[superGraph.length - 2][i] = 1;
- superGraph[i][superGraph.length - 1] = 1;
- continue;
- }
- //it should be connected by source "s"
-
- if(nothingEnter){
- superGraph[superGraph.length - 2][i] = 1;
- }
- //it should be connected by sink "t"
- if(nothingOut){
- superGraph[i][superGraph.length - 1] = 1000000;
- }
-
- }
- //copy original graph/content(the graph without source "s" and sink "t")
- //to superGraph(the graph with source "s" and sink "t"), return it
- for(int i = 0; i < graph.length; i++){
- for(int j = 0; j < graph.length; j++){
- superGraph[i][j] = graph[i][j];
- }
- }
- return superGraph;
- }
- }
复制代码 |
|