KM算法 模板

来源:互联网 发布:正整数分解质因数算法 编辑:程序博客网 时间:2024/06/06 00:06

2017年4月3日 | ljfcnyali
KM算法大意
1.运用贪心算法初始化标杆。
2.运用匈牙利算法找到完备匹配。
3.如果找不到,则通过修改标杆,增加一些边。
4.重复2,3的步骤,找到完备匹配时可结束。

KM算法实现
乱搞!
1.初始化,标杆为女生的最大期望值;
2.枚举每一个女生;
3.DFS尝试可否成功,成功则枚举下一个女生;
4.如果失败,减少期望值,返回3;
5.结束循环,进行答案计算.

模板
以HDU2255为例.

/*************************************************************************    > File Name: KM.cpp    > Author: ljf-cnyali    > Mail: ljfcnyali@gmail.com     > Created Time: 2017/4/3 14:30:16 ************************************************************************/#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define REP(i, a, b) for(int i = (a), _end_ = (b);i <= _end_; ++ i)#define mem(a) memset((a), 0, sizeof(a))#define str(a) strlen(a)const int maxn = 1010;const int INF = 1000000000;int n, m;int Map[maxn][maxn];int ex_Girl[maxn];int ex_Boy[maxn];bool vis_Girl[maxn];bool vis_Boy[maxn];int match[maxn];int slack[maxn];bool DFS(int Girl) {    vis_Girl[Girl] = true;    REP(Boy, 1, n) {        if(vis_Boy[Boy]) continue ;        int sum = ex_Girl[Girl] + ex_Boy[Boy] - Map[Girl][Boy];        if(sum == 0) {            vis_Boy[Boy] = true;            if(match[Boy] == -1 || DFS(match[Boy])) {                match[Boy] = Girl;                return true;            }        }        else {            slack[Boy] = min(slack[Boy], sum);        }    }    return false;}int KM() {    memset(match, -1, sizeof(match));    mem(ex_Boy);    REP(i, 1, n) {        ex_Girl[i] = Map[i][1];        REP(j, 2, n)            ex_Girl[i] = max(ex_Girl[i], Map[i][j]);    }    REP(i, 1, n) {        REP(j, 1, n)            slack[j] = INF;        while(1) {            mem(vis_Girl);            mem(vis_Boy);            if(DFS(i)) break ;            int sum = INF;            REP(j, 1, n)                if(!vis_Boy[j])                    sum = min(sum, slack[j]);            REP(j, 1, n) {                if(vis_Girl[j]) ex_Girl[j] -= sum;                if(vis_Boy[j]) ex_Boy[j] += sum;                else slack[j] -= sum;            }        }    }    int ans = 0;    REP(i, 1, n)        ans += Map[match[i]][i];    return ans;}int main() {#ifndef ONLINE_JUDGE    freopen("input.txt", "r", stdin);    freopen("output.txt", "w", stdout);#endif    while(~scanf("%d", &n)) {        REP(i, 1, n)            REP(j, 1, n)                scanf("%d", &Map[i][j]);        printf("%d\n", KM());    }    return 0;}

本文转自:http://ljf-cnyali.cn/index.php/archives/130

原创粉丝点击