二分图(Java)

//对于节点数目不同可以处理,
//Java语言实现,最基础未优化

public class ErFenTu {

	public static int m = 50;
	public static int n = 100;
	public static int[] lx = new int[m];
	public static int[] ly = new int[n];
	public static boolean[] sx = new boolean[m];
	public static boolean[] sy = new boolean[n];
	public static int[] cx = new int[n];//x对应y的坐标
	public static int[] match = new int[n];//大小为n(y对应x的坐标)
	public static int[][] weight;
        
        public static boolean path(int u){//范围到m
        sx[u] = true;
        for(int v = 0; v < n; v++){
            if(!sy[v] && lx[u] + ly[v] == weight[u][v]){
                sy[v] = true;
                if(match[v] == -1 || path(match[v])){
                    cx[u] = v;
                    match[v] = u;
                    return true;
                }
            }
        }
        return false;
    }
    
    public static int bestMatch(boolean maxsum){
        if(!maxsum){
            for(int i = 0; i < m; i++){
                for(int j = 0; j < n; j++){
                    weight[i][j] = - weight[i][j];
                }
            }
        }
        for(int i = 0; i < m; i++){
            lx[i] = Integer.MIN_VALUE;
            for(int j = 0; j < n; j++){
                if(lx[i] < weight[i][j]){
                    lx[i] = weight[i][j]; 
                }
            }
        }
        for(int i = 0; i < n; i++){
            ly[i] = 0;
            match[i] = -1;
        }
        
        for(int u = 0; u < m; u++){
            while(true){
                for(int i = 0; i < m; i++){
                    sx[i] = false;
                 }
                for(int i = 0; i < n; i++){
                    sy[i] = false;
                }
                if(path(u)){
                    break;
                }
                //修改标号
                int dx = Integer.MAX_VALUE;
                for(int i = 0; i < m; i++){
                    if(sx[i]){
                        for(int j = 0; j < n; j++){
                            if(!sy[j]){
                                dx = Math.min(lx[i] + ly[j] - weight[i][j], dx);
                            }
                        }
                    }
                }
                for(int i = 0; i < m; i++){
                    if(sx[i]){
                        lx[i] -= dx;
                    }
                }
                for(int i = 0; i < n; i++){
                    if(sy[i]){
                        ly[i] += dx;
                    }
                }
            }
        }
//        for(int i = 0; i < n; i++){
//            System.out.println(match[i]);
//        }
        int sum = 0; 
        for(int i = 0; i < n; i++){
            if(match[i] != -1){
                sum += weight[match[i]][i];
            }
            
        }
        if(!maxsum){
            sum = -sum;
            for(int i = 0; i < m; i++){
                for(int j = 0; j < n; j++){
                    weight[i][j] = -weight[i][j];
                }
            }
        }
        return sum;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值