KM最大匹配

KM算法详解+模板 - wenr - 博客园  http://www.cnblogs.com/wenruo/p/5264235.html

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 using namespace std;
  6
  7 #define MAXN 305
  8 #define inf 65553566
  9 int love[MAXN][MAXN];   /// 记录每个妹子和每个男生的好感度
 10 int ex_girl[MAXN];      /// 每个妹子的期望值
 11 int ex_boy[MAXN];       /// 每个男生的期望值
 12 bool vis_girl[MAXN];    /// 记录每一轮匹配匹配过的女生
 13 bool vis_boy[MAXN];     /// 记录每一轮匹配匹配过的男生
 14 int match[MAXN];        /// 记录每个男生匹配到的妹子 如果没有则为-1
 15 int slack[MAXN];        /// 记录每个汉子如果能被妹子倾心最少还需要多少期望值
 16
 17 int n,sum;
 18
 19 ///为女孩找匹配的男孩
 20 int find(int girl)
 21 {
 22     vis_girl[girl]=1;
 23     for(int boy=1;boy<=n;boy++)
 24     {
 25         if(vis_boy[boy]) continue;///如果男孩已经被标记过,则找下一个
 26         int gap=ex_girl[girl]+ex_boy[boy]-love[girl][boy];///看差距
 27         if(gap==0)
 28         {
 29             vis_boy[boy]=1;
 30             if(match[boy]==-1||find(match[boy]))///如果男孩未匹配过或者该男孩的妹子可以找其他人
 31             {
 32                 match[boy]=girl;///将女孩匹配给男
 33                 return 1;
 34             }
 35         }
 36         else
 37         {
 38             slack[boy]=min(slack[boy],gap);
 39         }
 40     }
 41     return 0;
 42 }
 43 void KM()
 44 {
 45     memset(match,-1,sizeof(match));
 46     memset(ex_boy,0,sizeof(ex_boy));
 47
 48     ///每个女生的初始期望值是与他相连的男生最大的好感度
 49     for(int i=1;i<=n;i++)
 50     {
 51         ex_girl[i]=love[i][1];
 52         for(int j=2;j<=n;j++)
 53         {
 54             ex_girl[i]=max(ex_girl[i],love[i][j]);
 55         }
 56     }
 57     ///尝试为每个女孩匹配男孩
 58     for(int i=1;i<=n;i++)
 59     {
 60         fill(slack+1,slack+n+1,inf);
 61         while(1)
 62         {
 63
 64               /// 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
 65               ///记录每轮匹配中南海女孩是否被尝试匹配过
 66             memset(vis_girl,0,sizeof(vis_girl));
 67             memset(vis_boy,0,sizeof(vis_boy));
 68             if(find(i))  break;///如果发现该女孩已经找到归宿,就进行下一个女孩
 69             int d=inf;
 70             for(int j=1;j<=n;j++)
 71                 if(!vis_boy[j])///看该男孩如果没有匹配的,就将最小的期望值给他
 72                 d=min(d,slack[j]);
 73
 74             for(int j=1;j<=n;j++)
 75             {
 76                 if(vis_girl[j])///如果女孩已经匹配,则女孩的期望值减去
 77                     ex_girl[j]-=d;
 78                 if(vis_boy[j])
 79                     ex_boy[j]+=d;
 80             }
 81         }
 82     }
 83 }
 84 int main()
 85 {
 86     while(scanf("%d",&n)!=EOF)
 87     {
 88         sum=0;
 89         for(int i=1;i<=n;i++)
 90             for(int j=1;j<=n;j++)
 91         {
 92             scanf("%d",&love[i][j]);
 93         }
 94         KM();
 95         for(int i=1;i<=n;i++)
 96         {
 97             sum+=love[match[i]][i];
 98         }
 99         printf("%d\n",sum);
100     }
101
102 }
时间: 2024-10-11 01:47:39

KM最大匹配的相关文章

HDU 3523 Image copy detection(KM最大匹配)

HDU 3523 Image copy detection 题目链接 题意:这题其实题意读懂就简单了,说白了就是1-n放到1-n列,每列的值为每列上数字和该数字的差的绝对值,然后求总和最小 思路:就一KM最大匹配 代码: #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std;

HDU 3722 Card Game(KM最大匹配)

HDU 3722 Card Game 题目链接 题意:给定一些字符串,每次可以选两个a,b出来,a的前缀和b的后缀的最长公共长度就是获得的值,字符串不能重复选,问最大能获得多少值 思路:KM最大匹配,两两串建边,跑最大匹配即可 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAXNODE

HDU 3718 Similarity(KM最大匹配)

HDU 3718 Similarity 题目链接 题意:给定一个标准答案字符串,然后下面每一行给一个串,要求把字符一种对应一种,要求匹配尽量多 思路:显然的KM最大匹配问题,位置对应的字符连边权值+1 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAXNODE = 27; typede

HDU 2853 (KM最大匹配)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2853 题目大意:二分图匹配费用流.①最大匹配②最小原配变动 解题思路: 如果去掉第二个要求,那么就是裸KM. 然而加上第二个要求,那么就需要一种新的建图方式. 建图 对于输入矩阵,每一条边,cost扩大K倍($K=n+1$) 对于原配,每一条边cost在扩大K倍基础上+1 KM 统计cost时,直接把cost整除K,然后累加. 并且Hash一下原配边的变动情况. 扩大K倍的作用 准确来说,K倍是为了

HDU 3315 My Brute(KM最大匹配)

HDU 3315 My Brute 题目链接 和HDU2835是一样的思路,利用把数字离散掉来多判断一个优先级 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAXNODE = 105; typedef int Type; const Type INF = 0x3f3f3f3f; str

HDU 2853 Assignment(KM最大匹配好题)

HDU 2853 Assignment 题目链接 题意:现在有N个部队和M个任务(M>=N),每个部队完成每个任务有一点的效率,效率越高越好.但是部队已经安排了一定的计划,这时需要我们尽量用最小的变动,使得所有部队效率之和最大.求最小变动的数目和变动后和变动前效率之差. 思路:对于如何保证改变最小,没思路,看了别人题解,恍然大悟,表示想法非常机智 试想,如果能让原来那些匹配边,比其他匹配出来总和相同的权值还大,对结果又不影响,那就简单了,这个看似不能做到,其实是可以做到的 数字最多选出50个,所

HDU 2426 Interesting Housing Problem(KM完美匹配)

HDU 2426 Interesting Housing Problem 题目链接 题意:n个学生,m个房间,给定一些学生想住房的喜欢度,找一个最优方案使得每个学生分配一个房间,并且使得喜欢度最大,注意这题有个坑,就是学生不会住喜欢度为负的房间 思路:很明显的KM最大匹配问题,喜欢度为负直接不连边即可 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm>

【图论】二分图匹配总结

二分图匹配总结 二分图匹配 1.二分图最大匹配.求两个集合内,每一个元素仅仅能用一次.两集合间存在一些匹配关系,求最大匹配多少对,利用匈牙利算法,对于每一个结点不断去找增广路去匹配 有几个重要性质: 1.最小点覆盖 = 最大匹配 2.最大独立集 = 总结点 - 最大匹配 模板: bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (vis[v]) continue; vis[v] = 1; i

Going Home(最大匹配km算法)

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20115   Accepted: 10189 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertica