zoukankan      html  css  js  c++  java
  • 算法学习_匈牙利算法

    匈牙利算法

    匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法

    该算法是求解二分图的完全匹配问题

    建图:把行号放左边点集,列号放在右边点集。

    关键是求该二分图的最小边覆盖点集使得每条边都被至少一个点覆盖。

    算法模板:

    //使用bfs实现
    int dfs(int e) {
    	for(int i = 1; i <= v; ++i) {
    		if(a[e][i] && !vis[i]) {
    			vis[i] = 1;
    			if(match[i] == -1 || dfs(match[i])) {//十分重要
    				match[i] = e;//在二分图中: 行e与列i 连线
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    

     例题1

    POJ3401

    input:
    3 4
    1 1
    1 3
    2 2
    3 2
    output:
    2
    

    问题描述:在N*N的矩阵里面,有k个星球。有一个神奇的武器,每次可以消灭一行或者一列的星球,问最少使用多少次武器可以消灭所有的星球。

    求解代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    using namespace std;
    int u;
    int p[1100][1100];
    int match[1100];
    int vis[1100];
    int dfs(int e) {	//匈牙利算法
    	for(int i = 1; i <= u; ++i) {
    		if(p[e][i] && !vis[i]) {
    			vis[i] = 1;
    			if(dfs(match[i]) || match[i] == -1) {
    				match[i] = e;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main () {
    	int n, k;
    	while(~scanf("%d%d", &n, &k)) {
    		u = n;
    		int ans = 0;
    		memset(p, 0, sizeof p);
    		memset(match, -1, sizeof match);
    		for(int i = 1; i <= k; ++i) {
    			int x, y;
    			scanf("%d%d", &x, &y);
    			p[x][y] = 1;
    		}
    		for(int i = 1; i <= n; ++i) {
    			memset(vis, 0, sizeof vis);
    			if(dfs(i))
    				ans++;
    		}
    		printf("%d
    ", ans);
    	}
    }
    

     例题2

    Hdu 2119

    input:
    3 3 
    0 0 0
    1 0 1
    0 1 0
    0
    output:
    2
    

     题意:与上题类似,不多累述

    求解代码:

    #include <bits/stdc++.h>
    using namespace std;
    int u, v;
    bool a[110][110];
    bool vis[110];
    int match[110];
    int dfs(int e) {
    	for(int i = 1; i <= v; ++i) {
    		if(a[e][i] && !vis[i]) {
    			vis[i] = 1;
    			if(match[i] == -1 || dfs(match[i])) {//十分重要
    				match[i] = e;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    
    int main () {
    	int n, m;
    	while(1) {
    		cin >> n;
    		if(n == 0) {
    			break;
    		}
    		cin >> m;
    		memset(a, 0, sizeof a);
    		memset(match, -1, sizeof match);
    		for(int i = 1; i <= n; ++i) {
    			for(int j = 1; j <= m; ++j) {
    				cin >> a[i][j];
    			}
    		}
    		u = n;
    		v = m;
    		int ans = 0;
    		for(int i = 1; i <= u; ++i) {
    			memset(vis, 0, sizeof vis);
    			if(dfs(i)) {
    				ans++;
    			}
    		}
    		cout << ans << endl;
    	}
    }
    
    作者:LightAc
    出处:https://www.cnblogs.com/lightac/
    联系:
    Email: dzz@stu.ouc.edu.cn
    QQ: 1171613053
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    JS 面向对象
    堆 栈
    考试题
    HTML Meta标签
    Nodejs 安装
    CSS3 背景图片的大小位置
    JS Math函数
    CSS3 巧用before after选择器
    计算机网络原理_数据链路层
    Asp.net_验证控件
  • 原文地址:https://www.cnblogs.com/lightac/p/12438821.html
Copyright © 2011-2022 走看看