如何使用Java解决最大流

来源:互联网 发布:团伙研发作弊软件 编辑:程序博客网 时间:2024/06/16 06:43

代码

  1. package maxflow;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.LinkedList;  
  5. import java.util.List;  
  6. import java.util.Queue;  
  7.   
  8. import util.EdgeUtil;  
  9. import util.NodeUtil;  
  10. import entry.Edge;  
  11. import entry.Node;  
  12. /** 
  13.  * Ford Fulkerson方法求最大流,这是一种迭代的方法,开始是,初始流为0,每次迭代中,课通过寻找一条增广路径来增加流值。反复进行这一过程,直至找不到任何增广路径 
  14.  * 本算法使用了Edmonds-Karp算法(一种对Ford Fulkerson方法的实现),在寻找增广路径时使用了寻找s到t的最短路径的方法。复杂度O(VE2) 
  15.  * @author xhw 
  16.  * 
  17.  */  
  18. public class FordFulkerson {  
  19.   
  20.     private static double residualNetwork[][]=null;  
  21.     private static double flowNetwork[][]=null;  
  22.       
  23.     /** 
  24.      * @param args 
  25.      */  
  26.     public static void main(String[] args) {  
  27.         double graph[][]={{0,16,13,0,0,0},  
  28.                           {0,0,10,12,0,0},  
  29.                           {0,4,0,0,14,0},  
  30.                           {0,0,9,0,0,20},  
  31.                           {0,0,0,7,0,4},  
  32.                           {0,0,0,0,0,0}};  
  33.           
  34.         System.out.println(edmondsKarpMaxFlow(graph,0,5));  
  35.   
  36.     }  
  37.     /** 
  38.      * 实现FordFulkerson方法的一种算法——edmondsKarp算法 
  39.      * @param graph 
  40.      * @param s 
  41.      * @param t 
  42.      * @return 
  43.      */  
  44.     public static double edmondsKarpMaxFlow(double graph[][],int s,int t)  
  45.     {  
  46.         int length=graph.length;  
  47.         //List<Node> nodeList=NodeUtil.generateNodeList(graph);  
  48.         double f[][]=new double[length][length];  
  49.         for(int i=0;i<length;i++)  
  50.         {  
  51.             for(int j=0;j<length;j++)  
  52.             {  
  53.                 f[i][j]=0;  
  54.             }  
  55.         }  
  56.         double r[][]=residualNetwork(graph,f);  
  57.           
  58.         Node result=augmentPath(r,s,t);  
  59.         double sum=0;  
  60.         while(result!=null)  
  61.         {  
  62.             double cfp=0;  
  63.             cfp=minimumAugment(r,result);  
  64.             //说明已经没有增广路径了  
  65.             if(cfp==0)  
  66.             {  
  67.                 break;  
  68.             }  
  69.               
  70.             while(result.getParent()!=null)  
  71.             {  
  72.                 Node parent=result.getParent();  
  73.                   
  74.                 f[parent.nodeId][result.nodeId]+=cfp;  
  75.                 f[result.nodeId][parent.nodeId]=-f[parent.nodeId][result.nodeId];  
  76.                   
  77.                 result=parent;  
  78.             }  
  79.               
  80.             sum+=cfp;  
  81.             r=residualNetwork(graph,f);  
  82.             result=augmentPath(r,s,t);  
  83.               
  84.         }  
  85.           
  86.         residualNetwork=r;  
  87.         flowNetwork=calculateFlowNetwork(graph,r);  
  88.           
  89.         /*for(int i=0;i<length;i++) 
  90.         { 
  91.             for(int j=0;j<length;j++) 
  92.             { 
  93.                  
  94.                 System.out.print((flowNetwork[i][j]>0?flowNetwork[i][j]:0.0)+" "); 
  95.             } 
  96.             System.out.println(); 
  97.         }*/  
  98.         return sum;  
  99.     }  
  100.     /** 
  101.      * 计算最终的流网络,也就是最大流网络 
  102.      * @param graph 
  103.      * @param r 
  104.      * @return 
  105.      */  
  106.     private static double[][] calculateFlowNetwork(double[][] graph, double[][] r) {  
  107.         int length=graph.length;  
  108.         double f[][]=new double[graph.length][graph.length];  
  109.         for(int i=0;i<length;i++)  
  110.         {  
  111.             for(int j=0;j<length;j++)  
  112.             {  
  113.                 f[i][j]=graph[i][j]-r[i][j];  
  114.             }  
  115.         }  
  116.         return f;  
  117.     }  
  118.   
  119.     /** 
  120.      * 确定增广路径可扩充的流值 
  121.      * @param graph 
  122.      * @param result 
  123.      * @return 
  124.      */  
  125.     public static double minimumAugment(double graph[][],Node result)  
  126.     {  
  127.         double cfp=Double.MAX_VALUE;  
  128.         while(result.getParent()!=null)  
  129.         {  
  130.             Node parent=result.getParent();  
  131.               
  132.             double weight=graph[parent.nodeId][result.nodeId];  
  133.             if(weight<cfp&&weight>0)  
  134.             {  
  135.                 cfp=weight;  
  136.             }  
  137.             else if(weight<=0)  
  138.             {  
  139.                 cfp=0;  
  140.                 break;  
  141.             }  
  142.             result=parent;  
  143.         }  
  144.         return cfp;  
  145.     }  
  146.   
  147.     /** 
  148.      * 计算残余网络 
  149.      * @param c 
  150.      * @param f 
  151.      * @return 
  152.      */  
  153.     private static double[][] residualNetwork(double c[][],double f[][]) {  
  154.         int length=c.length;  
  155.         double r[][]=new double[length][length];  
  156.         for(int i=0;i<length;i++)  
  157.         {  
  158.             for(int j=0;j<length;j++)  
  159.             {  
  160.                 r[i][j]=c[i][j]-f[i][j];  
  161.             }  
  162.         }  
  163.           
  164.         return r;  
  165.     }  
  166.   
  167.   
  168.     /** 
  169.      * 广度优先遍历,寻找增光路径,也是最短增广路径 
  170.      * @param graph 
  171.      * @param s 
  172.      * @param t 
  173.      * @return 
  174.      */  
  175.     public static Node augmentPath(double graph[][],int s,int t)  
  176.     {  
  177.         Node result=null;  
  178.         List<Node> nodeList=NodeUtil.generateNodeList(graph);  
  179.         nodeList.get(s).distance=0;  
  180.         nodeList.get(s).state=1;  
  181.           
  182.         Queue<Node> queue=new LinkedList<Node>();  
  183.         queue.add(nodeList.get(s));  
  184.           
  185.         while(!queue.isEmpty())  
  186.         {  
  187.             Node u=queue.poll();  
  188.             for(Node n:u.getAdjacentNodes())  
  189.             {  
  190.                 if(n.state==0)  
  191.                 {  
  192.                     n.state=1;  
  193.                     n.distance=u.distance+1;  
  194.                     n.setParent(u);  
  195.                     queue.add(n);  
  196.                 }  
  197.             }  
  198.             u.state=2;  
  199.             if(u.nodeId==t)  
  200.             {  
  201.                 result=u;  
  202.                 break;  
  203.             }  
  204.         }  
  205.         return  result;  
  206.           
  207.     }  
  208.   
  209.     public static double[][] getResidualNetwork() {  
  210.               
  211.         return residualNetwork;  
  212.               
  213.     }  
  214.   
  215.   
  216.     public static double[][] getFlowNetwork() {  
  217.         return flowNetwork;  
  218.     }  
  219.   
  220.   
  221.   
  222. }  

原创粉丝点击