hdu 2255 二分图最大权匹配 *

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

kuangbin模板题

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <iostream>
 5 using namespace std;
 6 
 7 /*  KM算法
 8  *   复杂度O(nx*nx*ny)
 9  *  求最大权匹配
10  *   若求最小权匹配,可将权值取相反数,结果取相反数
11  *  点的编号从0开始
12  */
13 const int N = 310;
14 const int INF = 0x3f3f3f3f;
15 int nx,ny;//两边的点数
16 int g[N][N];//二分图描述
17 int linker[N],lx[N],ly[N];//y中各点匹配状态,x,y中的点标号
18 int slack[N];
19 bool visx[N],visy[N];
20 
21 bool DFS(int x)
22 {
23     visx[x] = true;
24     for(int y = 0; y < ny; y++)
25     {
26         if(visy[y])continue;
27         int tmp = lx[x] + ly[y] - g[x][y];
28         if(tmp == 0)
29         {
30             visy[y] = true;
31             if(linker[y] == -1 || DFS(linker[y]))
32             {
33                 linker[y] = x;
34                 return true;
35             }
36         }
37         else if(slack[y] > tmp)
38             slack[y] = tmp;
39     }
40     return false;
41 }
42 int KM()
43 {
44     memset(linker,-1,sizeof(linker));
45     memset(ly,0,sizeof(ly));
46     for(int i = 0;i < nx;i++)
47     {
48         lx[i] = -INF;
49         for(int j = 0;j < ny;j++)
50             if(g[i][j] > lx[i])
51                 lx[i] = g[i][j];
52     }
53     for(int x = 0;x < nx;x++)
54     {
55         for(int i = 0;i < ny;i++)
56             slack[i] = INF;
57         while(true)
58         {
59             memset(visx,false,sizeof(visx));
60             memset(visy,false,sizeof(visy));
61             if(DFS(x))break;
62             int d = INF;
63             for(int i = 0;i < ny;i++)
64                 if(!visy[i] && d > slack[i])
65                     d = slack[i];
66             for(int i = 0;i < nx;i++)
67                 if(visx[i])
68                     lx[i] -= d;
69             for(int i = 0;i < ny;i++)
70             {
71                 if(visy[i])ly[i] += d;
72                 else slack[i] -= d;
73             }
74         }
75     }
76     int res = 0;
77     for(int i = 0;i < ny;i++)
78         if(linker[i] != -1)
79             res += g[linker[i]][i];
80     return res;
81 }
82 //HDU 2255
83 int main()
84 {
85     int n;
86     while(scanf("%d",&n) == 1)
87     {
88         for(int i = 0;i < n;i++)
89             for(int j = 0;j < n;j++)
90                 scanf("%d",&g[i][j]);
91         nx = ny = n;
92         printf("%d\n",KM());
93     }
94     return 0;
95 }

 

posted @ 2015-07-04 22:57  miao_a_miao  阅读(135)  评论(0编辑  收藏  举报