java 二分图带权匹配_算法笔记_139:二分图的最大权匹配(Java)

该博客介绍了一种使用Java实现的求解二分图最大权匹配的算法,通过匈牙利算法查找增广路径,并给出了完整的代码示例。在代码中,博主详细解释了如何初始化权重值、寻找最小权匹配以及调整权重的过程,最终计算并输出最大权匹配的总权重。
摘要由CSDN通过智能技术生成

packagecom.liuzhen.practice;importjava.util.Scanner;public classMain {public static int MAX = 100;public static intn;public static int[][] value = new int[MAX][MAX]; //给定二分图的权重值

public static int[] lx = new int[MAX]; //记录二分图左半部分顶点的可行顶标

public static int[] ly = new int[MAX]; //记录二分图右半部分顶点的可行顶标

public static boolean[] sx = new boolean[MAX];//用于记录二分图左半部分顶点是否在最终结果中

public static boolean[] sy = new boolean[MAX];//用于记录二分图右半部分顶点是否在最终结果中

public static int[] pre = new int[MAX]; //用于记录最终结果中顶点y匹配的顶点x

public boolean dfs(int x) { //采用匈牙利算法找增广路径

sx[x] = true; //代表左半部分顶点x包含在最终结果中

for(int y = 0;y < n;y++) {if(!sy[y] && lx[x] + ly[y] ==value[x][y]) {

sy[y]= true; //代表右半部分顶点y包含在最终结果中

if(pre[y] == -1 ||dfs(pre[y])) {

pre[y]=x;return true;

}

}

}return false;

}public int getKM(intjudge) {if(judge == -1) { //代表寻找二分图的最小权匹配

for(int i = 0;i < n;i++)for(int j = 0;j < n;j++)

value[i][j]= -1 * value[i][j]; //把权值变为相反数,相当于找最大权匹配

}//初始化lx[i]和ly[i]

for(int i = 0;i < n;i++) {

ly[i]= 0;

lx[i]=Integer.MIN_VALUE;for(int j = 0;j < n;j++) {if(value[i][j] >lx[i])

lx[i]=value[i][j];

}

}for(int i = 0;i < n;i++)

pre[i]= -1; //初始化右半部分顶点y的匹配顶点为-1

for(int x = 0;x < n;x++) { //从左半部分顶点开始,寻找二分图完美匹配的相等子图完美匹配

while(true) {for(int i = 0;i < n;i++) {//每次寻找x的增广路径,初始化sx[i]和sy[i]均为被遍历

sx[i] = false;

sy[i]= false;

}if(dfs(x)) //找到从x出发的增广路径,结束循环,寻找下一个x的增广路径

break;//下面对于没有找到顶点x的增广路径进行lx[i]和ly[i]值的调整

int min =Integer.MAX_VALUE;for(int i = 0;i < n;i++) {if(sx[i]) { //当sx[i]已被遍历时

for(int j = 0;j < n;j++) {if(!sy[j]) { //当sy[j]未被遍历时

if(lx[i] + ly[j] - value[i][j]

min= lx[i] + ly[j] -value[i][j];

}

}

}

}if(min == 0)return -1;for(int i = 0;i < n;i++) {if(sx[i])

lx[i]= lx[i] -min;if(sy[i])

ly[i]= ly[i] +min;

}

}

}int sum = 0;for(int y = 0;y < n;y++) {

System.out.println("y顶点"+y+"和x顶点"+pre[y]+"匹配");if(pre[y] != -1)

sum= sum +value[pre[y]][y];

}if(judge == -1)

sum= -1 *sum;returnsum;

}public static voidmain(String[] args) {

Main test= newMain();

Scanner in= newScanner(System.in);

n=in.nextInt();int k = in.nextInt(); //给定二分图的有向边数目

for(int i = 0;i < k;i++) {int x =in.nextInt();int y =in.nextInt();int v =in.nextInt();

value[x][y]=v;

}

System.out.println(test.getKM(1));

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值