最大流
package 算法课程实验;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/**@author : fjl2401 创建时间:2017年12月17日 下午1:37:09
demo:1 maxvalue:50
4 5
1 2 40
2 3 30
1 4 20
3 4 10
2 4 20
1 4
demo:2 maxvalue:19
7 9
1 2 10
2 3 2
1 3 10
2 4 4
2 5 8
5 4 6
5 7 10
4 7 10
3 5 9
*/
public class Six {
int flag[];
int last[];
int Graph[][];
int from;
int to;
public Six() {
Graph=input();
}
public int [][] input(){
int a[][];
//input
System.out.println("请输入图的节点数和插入的边数,用逗号隔开");
Scanner scanner=new Scanner(System.in);
String xString=scanner.nextLine();
String string[]=xString.split(" ");
//n边数目,num节点数
int num=Integer.parseInt(string[0]);
int n=Integer.parseInt(string[1]);
a=new int[num+1][num+1];
//初始化
for (int i = 0; i < a.length; i++) {
for (int j = 0; j <a.length; j++) {
a[i][j]=-1;
}
}
System.out.println("请输入起点,终点,权重,用空格隔开");
for (int i = 0; i <n; i++) {
String sd=scanner.nextLine();
String sds[]=sd.split(" ");
a[Integer.parseInt(sds[0])][Integer.parseInt(sds[1])]=Integer.parseInt(sds[2]);
}
System.out.println("请输入源点和汇点,用空格隔开");
String sdString=scanner.nextLine();
String sources[]=sdString.split(" ");
from=Integer.parseInt(sources[0]);
to=Integer.parseInt(sources[1]);
scanner.close();
flag=new int [a.length];
last=new int [a.length];//上一个点
return a;
}
//bfs搜索道路
Boolean Search(int source,int t){
//初始化距离和颜色
for (int i = 0; i < Graph.length; i++) {
flag[i]=0;
last[i]=-1;
}
Queue<Integer> aQueue=new LinkedList<>();
//将初始点加入队列
aQueue.add(source);
last[source]=-1;
flag[source]=1;
while(!aQueue.isEmpty()){
int lable=aQueue.remove();
for (int i = 0; i < Graph.length; i++) {
if (Graph[lable][i]>0&&flag[i]==0) {
flag[i]=1;
last[i]=lable;
if (i==t) {
return true;
}
aQueue.add(i);
}
}
}
return false;
}
//输出图
public void output(){
for (int i = 1; i < Graph.length; i++) {
for (int j = 1; j < Graph.length; j++) {
System.out.print(Graph[i][j]+" ");
}
System.out.println();
}
}
int EK() {
int allValue=0;
for (int i = 0; i < Graph.length; i++) {
for (int j = 0; j < Graph.length; j++) {
if (Graph[i][j]!=-1&&Graph[i][j]!=0) {
Graph[j][i]=0;
}
}
}
while(Search(from, to)) {
int minvalue=10000;
//找出这条bfs出来的道路上的最大容量
for (int j =to; j!=from; j=last[j]) {
minvalue=min(minvalue, Graph[last[j]][j]);
}
allValue+=minvalue;
//给这条路上的所有边减掉最大容量,同时给反向边增加容量
for (int i =to; i!=from; i=last[i]) {
Graph[last[i]][i]-=minvalue;
Graph[i][last[i]]+=minvalue;
}
}
return allValue;
}
int min(int i,int j) {
if (i>j) {
return j;
}
else {
return i;
}
}
public static void main(String[] args) {
Six a=new Six();
int weight=a.EK();
System.out.println(weight);
}
}
思想 :
用while循环 dfs找出剩余网络,找出dfs路径可承受的最大流量,减去最大流,同时反向边增加最大流,反向边的容量减少代表着正向边容量的增加。 相当于给了正向边一个返回的机会。