最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱

题目传送门

 1 /*
 2     KM:裸题第一道,好像就是hungary的升级版,不好理解,写点注释
 3         KM算法用来解决最大权匹配问题: 在一个二分图内,左顶点为X,右顶点为Y,现对于每组左右连接Xi,Yj有权w(i,j),
 4         求一种匹配使得所有w(i,j)的和最大。也就是最大权匹配一定是完备匹配。如果两边的点数相等则是完美匹配。
 5         如果点数不相等,其实可以虚拟一些点,使得点数相等,也成为了完美匹配。最大权匹配还可以用最大流去解决
 6 */
 7 #include <cstdio>
 8 #include <algorithm>
 9 #include <cstring>
10 using namespace std;
11
12 const int MAXN = 3e2 + 10;
13 const int INF = 0x3f3f3f3f;
14 int x[MAXN], y[MAXN], w[MAXN][MAXN];
15 int lx[MAXN], ly[MAXN];
16 bool visx[MAXN], visy[MAXN];
17 int n, d;
18
19 bool DFS(int u)    {        //hungary算法
20     visx[u] = true;
21     for (int i=1; i<=n; ++i)    {
22         if (x[u] + y[i] == w[u][i] && !visy[i])    {
23             visy[i] = true;
24             if (ly[i] == -1 || DFS (ly[i]))    {
25                 ly[i] = u;    return true;
26             }
27         }
28         else if (x[u] + y[i] > w[u][i])    d = min (d, x[u] + y[i] - w[u][i]);        //更新d,贪心思想
29     }
30
31     return false;
32 }
33
34 void KM(void)    {
35     for (int i=1; i<=n; ++i)    {
36         x[i] = 0;
37         for (int j=1; j<=n; ++j)    {
38             x[i] = max (x[i], w[i][j]);        //初始x标杆为最大值w,y为0
39         }
40     }
41
42     memset (y, 0, sizeof (y));
43     memset (ly, -1, sizeof (ly));
44     for (int i=1; i<=n; ++i)    {
45         while (true)    {
46             memset (visx, false, sizeof (visx));
47             memset (visy, false, sizeof (visy));
48             d = INF;
49             if (DFS (i))    break;            //找到增广轨,退出
50             for (int i=1; i<=n; ++i)    {        //没有找到,对标杆进行调整
51                 if (visx[i])    x[i] -= d;
52                 if (visy[i])    y[i] += d;
53             }
54         }
55     }
56
57     int res = 0;
58     for (int i=1; i<=n; ++i)    {
59         res += x[i] + y[i];
60     }
61     printf ("%d\n", res);
62 }
63
64 int main(void)    {        //HDOJ 2255 奔小康赚大钱
65     //freopen ("HDOJ_2255.in", "r", stdin);
66
67     while (scanf ("%d", &n) == 1)    {
68         for (int i=1; i<=n; ++i)    {
69             for (int j=1; j<=n; ++j)    {
70                 scanf ("%d", &w[i][j]);
71             }
72         }
73         KM ();
74     }
75
76     return 0;
77 }
时间: 2024-11-08 11:41:09

最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱的相关文章

最大流增广路(KM算法) HDOJ 1533 Going Home

题目传送门 1 /* 2 最小费用流:KM算法是求最大流,只要w = -w就可以了,很经典的方法 3 */ 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstring> 8 using namespace std; 9 10 const int MAXN = 1e2 + 10; 11 const int INF = 0x3f3f3f3f; 12 int x

最大流增广路(KM算法) HDOJ 1853 Cyclic Tour

题目传送门 1 /* 2 KM: 相比HDOJ_1533,多了重边的处理,还有完美匹配的判定方法 3 */ 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstring> 8 using namespace std; 9 10 const int MAXN = 1e2 + 10; 11 const int INF = 0x3f3f3f3f; 12 int x

hdu 2255 奔小康赚大钱(KM算法)

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

[ACM] HDU 2255 奔小康赚大钱 (二分图最大权匹配,KM算法)

奔小康赚大钱 Problem Description 传说在遥远的地方有一个很富裕的村落,有一天,村长决定进行制度改革:又一次分配房子. 这但是一件大事,关系到人民的住房问题啊. 村里共同拥有n间房间,刚好有n家老百姓,考虑到每家都要有房住(假设有老百姓没房子住的话.easy引起不安定因素),每家必须分配到一间房子且仅仅能得到一间房子. 还有一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.因为老百姓都比較富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比方有3间房

HDU 2255 ——奔小康赚大钱——————【KM算法裸题】

奔小康赚大钱 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2255 Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到

HDU 2255 奔小康赚大钱 (KM算法 模板)

A - 奔小康赚大钱 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子.

HDU 2255 奔小康赚大钱 KM算法题解

KM算法求的是完备匹配下的最大权匹配,是Hungary算法的进一步,由于Hungary算法是最大匹配的算法,不带权. 经典算法,想不出来的了,要參考别人的.然后消化吸收吧. 由于真的非常复杂的算法. 我理解算法匹配思想: 1 開始的时候,全部边都记录自己的最优匹配,无论有没有冲突 2 递归循环的时候.假设找不到自己的最优匹配,那么就找次要匹配 3 次要匹配不行,继续找下一个次优匹配,全部点都一定要找到解 难点: 怎样记录这些信息,以便循环处理全部点. 牵涉到非常多什么增广路,交错树之类的,名词,

hdu 2255奔小康赚大钱 KM算法模板

题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=2255 一,KM算法:(借助这个题写一下个人对km的理解与km模板) KM算法主要是用来求解图的最优匹配的. 1.带权二分图:  在二分图中每一条边(x.y)相应一个权值Wi这样的二分图叫带权二分图. 一个匹配的权值就是该匹配中全部边的权值之和. 2,最优匹配: 权值最大的一个完美匹配.叫做最优匹配.       <km算法思想> 对于一个带权全然二分图:G(V.E),对于当中每一条边(x.y)边

hdu 2255 奔小康赚大钱 (km算法模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2255 解题思路: 了解km算法以后,就可以直接套用km算法,km算法:完备匹配下的最大权匹配, 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 #define maxn 310