最大流DINIC演算法JAVA板子
阿新 • • 發佈:2018-11-11
推薦一條部落格:
https://www.cnblogs.com/SYCstudio/p/7260613.html
講解得比較細緻。
然後自己理解了一下寫了個JAVA得板子,和哪個差不多,去把HDU一道板子題A了:
http://acm.hdu.edu.cn/showproblem.php?pid=3549
之前寫過一個EK演算法,不過據說不常用:
https://blog.csdn.net/King8611/article/details/81171248
程式碼:
import java.util.*; import java.io.*; public class Main { static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); static int grade[]; static int s,t; //超級源,超級匯 static int n; //定點個數 /*前向星存邊*/ static int head[]; static Edge[] e; static int len; //==================== static void addEdge(int a,int b,int c) { //新增節點 e[len]=new Edge(b,head[a],c); //前向星儲存邊 head[a]=len; len++; } static void add(int a,int b,int c) { //新增正節點和反節點 addEdge(a,b,c); addEdge(b,a,0); } static boolean bfs() { //bfs分層 LinkedList<Integer> list=new LinkedList<Integer>(); //一個佇列,用於分層 grade=new int[n+1]; list.offer(s); grade[s]=1; while(!list.isEmpty()) { int cur=list.poll(); if(cur==t)return true; for(int i=head[cur];i!=-1;i=e[i].next) { int v=e[i].v; if(grade[v]==0&&e[i].w!=0) { grade[v]=grade[cur]+1; list.offer(v); } } } return false; } static int dfs(int u,int dist) { //dfs求那啥流量 if(u==t) //找到匯點 return dist; for(int i=head[u];i!=-1;i=e[i].next) { if(grade[e[i].v]-1==grade[u]&&e[i].w!=0) { int di=dfs(e[i].v,Math.min(dist,e[i].w)); if (di>0){ //如果存在一個流,做相應操作 e[i].w-=di; e[i^1].w+=di; return di; } } } return 0; } static int Max_Flow() { //求最大流,不斷bfs,dfs直到分層不見t int ans=0; while(bfs()) { int d; do { d=dfs(s,Integer.MAX_VALUE); ans+=d; } while(d!=0); } return ans; } static void init() { //重置函式 len=0; e=new Edge[3000]; grade=new int[n+1]; head=new int[n+1]; for(int i=0;i<=n;i++) head[i]=-1; s=1; t=n; } public static void main(String[] args) throws Exception{ int t=getInt(); for(int i=1;i<=t;i++){ n=getInt(); int m=getInt(); init(); while(m--!=0) { add(getInt(),getInt(),getInt()); } System.out.println("Case "+i+": "+Max_Flow()); } } static int getInt() throws Exception { in.nextToken(); return (int)in.nval; } } class Edge{ int next; //對應的下一條邊 int v; //點 int w; //容量 public Edge() {} public Edge(int a,int b,int c) { //點,下一條邊,容量 this.v=a; this.next=b; this.w=c; } }