二分图最佳匹配

  1 /*
  2 * this code is made by bjfu_song
  3 * Problem: 1227
  4 * Verdict: Accepted
  5 * Submission Date: 2014-10-05 14:53:22
  6 * Time: 132MS
  7 * Memory: 2340KB
  8 */
  9 #include<iostream>
 10 #include<stdio.h>
 11 #include<string.h>
 12 #include<algorithm>
 13 using namespace std;
 14 #include <string.h>
 15 #define MAXN 410
 16 #define inf 1000000000
 17 #define _clr(x) memset(x,-1,sizeof(int)*MAXN)
 18
 19 int f[1010],f1[MAXN],f2[MAXN];
 20 int n;
 21 int w[MAXN][MAXN];
 22 /******************************************************
 23 二分图最佳匹配 (kuhn munkras 算法 O(m*m*n)).
 24 邻接矩阵形式 。  返回最佳匹配值,传入二分图大小m,n
 25 邻接矩阵 mat ,表示权,match1,match2返回一个最佳匹配,为匹配顶点的match值为-1,
 26 一定注意m<=n,否则循环无法终止,最小权匹配可将全职取相反数。
 27 初始化:  for(i=0;i<MAXN;i++)
 28              for(j=0;j<MAXN;j++) mat[i][j]=-inf;
 29 对于存在的边:mat[i][j]=val;//注意不能负值
 30 · 可能存在没有匹配的边。
 31 ********************************************************/
 32
 33 void kuhn_munkras(int m, int n, int mat[][MAXN], int* match1, int* match2) {
 34     int s[MAXN], t[MAXN], l1[MAXN], l2[MAXN], p, q, ret = 0, i, j, k;
 35
 36     for( i=0;i<1010;i++) match1[i] = -1;
 37     for (i = 0; i < m; i++) {
 38         for (l1[i] = -inf, j = 0; j < n; j++)
 39             l1[i] = mat[i][j] > l1[i] ? mat[i][j] : l1[i];
 40     }
 41     for (i = 0; i < n; l2[i++] = 0)
 42         ;
 43     for (_clr(match1), _clr(match2), i = 0; i < m; i++) {
 44         for (_clr(t), s[p = q = 0] = i; p <= q && match1[i] < 0; p++)
 45             for (k = s[p], j = 0; j < n && match1[i] < 0; j++)
 46                 if (l1[k] + l2[j] == mat[k][j] && t[j] < 0) {
 47                     s[++q] = match2[j], t[j] = k;
 48                     if (s[q] < 0)
 49                         for (p = j; p >= 0; j = p)
 50                             match2[j] = k = t[j], p = match1[k], match1[k] = j;
 51                 }
 52         if (match1[i] < 0) {
 53             for (i--, p = inf, k = 0; k <= q; k++)
 54                 for (j = 0; j < n; j++)
 55                     if (t[j] < 0 && l1[s[k]] + l2[j] - mat[s[k]][j] < p)
 56                         p = l1[s[k]] + l2[j] - mat[s[k]][j];
 57             for (j = 0; j < n; l2[j] += t[j] < 0 ? 0 : p, j++)
 58                 ;
 59             for (k = 0; k <= q; l1[s[k++]] -= p)
 60                 ;
 61         }
 62     }
 63     for (i = 0; i < m; i++) {// if处理无匹配的情况!!
 64         if (match1[i] < 0)
 65             match1[i] = -1;
 66         if (mat[i][match1[i]] <= -inf)
 67             match1[i] = -1;
 68     }
 69 }
 70
 71 int main()
 72 {
 73     //freopen("in.txt","r",stdin);
 74     while(scanf("%d",&n)!=EOF)
 75     {
 76         for(int i=0;i<n;i++) scanf("%d",&f[i]); //每个孩子的权值
 77         for(int i=0;i<MAXN;i++)
 78             for(int j=0;j<MAXN;j++) w[i][j] = -inf;
 79         for(int i=0; i<n; i++){
 80             int t;scanf("%d",&t);
 81             for(int j=1; j<=t; j++){
 82                 int z;scanf("%d",&z);
 83                 w[i][z-1] = f[i];  //对第z个孩子的喜爱程度为权值
 84             }
 85         }
 86 //        for(int i=0;i<n;i++){
 87 //          for(int j=0;j<n;j++){
 88 //              printf("%d ",w[i][j]);
 89 //          }printf("\n");
 90 //        }
 91        // for(int i=0;i<1010;i++) f1[i] = -1;
 92
 93         kuhn_munkras(n,n,w,f1,f2);
 94
 95         //printf("%d\n",n);
 96
 97         for(int i=0; i<n; i++)
 98         {
 99             if(i) printf(" ");
100             if(f1[i]==-1) printf("0");
101             else printf("%d",f1[i]+1);
102         }
103     }
104     return 0;
105 }
时间: 2024-12-29 07:03:49

二分图最佳匹配的相关文章

hdu2255 奔小康赚大钱 二分图最佳匹配--KM算法

传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子.另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(

Regionals 2015 &gt;&gt; Asia - Tehran &gt;&gt; 7530 - Cafebazaar【二分图最佳匹配】【KM】【最大费用流】

Regionals 2015 >> Asia - Tehran >> 7530 - Cafebazaar 题目链接:7530 题目大意:一个公司有n个开发者,有m个APP可开发.其中一些开发者必选,一些APP必选.已知每个开发者开发每个APP的收益,求最大收益.(每个开发者最多开发一个APP,每个APP最多一个人开发) 题目思路: 解法一:二分图最佳匹配(KM算法) 增加一些虚开发者和虚app,非必要app可以被虚开发者开发,收益为0,反过来非必要开发者可以开发虚app,收益为0.

HDU2255 奔小康赚大钱【二分图最佳匹配】

题目链接: http://acm.hdu.edu.cn/showproblem.php? pid=2255 题目大意: 村里要分房子. 有N家老百姓,刚好有N间房子.考虑到每家都要有房住,每家必须分配到一间房子且 仅仅能分配到一间房子.另外, 村长为了得到最大利益,让老百姓对房子进行估价. 比方有3件房子,一 家老百姓能够对第一间出10万,对第二间出2万,对第三间出4万.第二家老百姓能够对第一间出8万, 对第二家出3万,对第三间出5万.那么问题来了:怎么分配,才干使利益最大化. (村民房子不一定

POJ2195 Going Home【二分图最佳匹配】

题目链接: http://poj.org/problem?id=2195 题目大意: 在一个N*M的矩阵中,有M个人和M个房子,每个人要安排一个房子,每个房子只能安排一个人. 而每个人移动一步需要一美元.那么问题来了:求为每个人安排房子移动所需要的金钱最小值是多 少. 思路: 做一个二分图,一边为人,另一边为房子,如果把人和房子之间的距离作为边权的话,问题就变成 了求带权二分图最小权和的最佳匹配.这里我们为了方便计算,吧人和房子之间的距离的负值作为 边权,那么就变成了求带权二分图最大权和的最佳匹

二分图最佳匹配,求最大权匹配或最小权匹配

Beloved Sons http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1338 题意:国王有N个儿子,现在每个儿子结婚都能够获得一定的喜悦值,王子编号为1-N,有N个女孩的编号同样为1-N,每个王子心中都有心仪的女孩,现在问如果安排,能够使得题中给定的式子和最大. 分析:其实题目中那个开根号是个烟雾弹,只要关心喜悦值的平方即可.那么对王子和女孩之间构边,边权为喜悦值的平方,对于每一个王子虚拟出一个女孩边权为0,这样是为了所

HDU2255 奔小康赚大钱 【二分图最佳匹配&#183;KM算法】

奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3898    Accepted Submission(s): 1691 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考

二分图&#39;最佳匹配&#39; KM算法

讲得很清楚的博客  推荐! 点我?? 附上一模板题 // hdu 2255(求最大权和) 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int INF = 0x3f3f3f3f; 5 const int MAXN = 300+5; 6 7 int n; 8 int w[MAXN][MAXN];// 权值数组 9 int cx[MAXN], cy[MAXN];// "标杆&qu

hdu 2063 过山车(二分图最佳匹配)

经典的二分图最大匹配问题,因为匈牙利算法我还没有认真去看过,想先试试下网络流的做法,即对所有女生增加一个超级源,对所有男生增加一个超级汇,然后按照题意的匹配由女生向男生连一条边,跑一个最大流就是答案(以上所有边容量均为 1 ),我是直接上 Dinic 算法的模板的: 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #include<algorit

POJ3565 Ants【二分图最佳匹配】

题目链接: http://poj.org/problem?id=3565 题目大意: 在坐标系中有N只蚂蚁,N棵苹果树,给你蚂蚁和苹果树的坐标.让每只蚂蚁去一棵苹果树, 一棵苹果树对应一只蚂蚁.这样就有N条直线路线,问:怎样分配,才能使总路程和最小,且 N条线不相交. 思路: 用一个图来说明思路. 假设A.B为蚂蚁,C.D为苹果树.则存在两种匹配:第一种是AD.BC,第二种是AC.BD. 根据三角形不等式AD+BC < AC+BD,最后得到很重要的一个性质--满足总路程之和最小 的方案一定不相交