http://acm.split.hdu.edu.cn/showproblem.php?pid=2255

Problem Description

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

Input

输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。

Output

请对每组数据输出最大的收入值,每组的输出占一行。

Sample Input

2
100 10
15 23

Sample Output

123

AC代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<climits>

#include<algorithm>

using namespace std;

#define N 310

int map[N][N];

bool visitx[N], visity[N];

int lx[N], ly[N];

int match[N];

int n;

bool Hungary(int u) //匈牙利算法

{

visitx[u] = true;

for(int i = 0; i < n; ++i)

{

if(!visity[i] && lx[u] + ly[i] == map[u][i])

{

visity[i] = true;

if(match[i] == -1 || Hungary(match[i]))

{

match[i] = u;

return true;

}

}

}

return false;

}

void KM_perfect_match()

{

int temp;

memset(lx, 0, sizeof(lx)); //初始化顶标

memset(ly, 0, sizeof(ly)); //ly[i]为0

for(int i = 0; i < n; ++i) //lx[i]为权值最大的边

for(int j = 0; j < n; ++j)

lx[i] = max(lx[i], map[i][j]);

for(int i = 0; i < n; ++i) //对n个点匹配

{

while(1)

{

memset(visitx, false, sizeof(visitx));

memset(visity, false, sizeof(visity));

if(Hungary(i)) //匹配成功

break;

else //匹配失败,找最小值

{

temp = INT_MAX;

for(int j = 0; j < n; ++j) //x在交错树中

if(visitx[j])

for(int k = 0; k < n; ++k) //y在交错树外

if(!visity[k] && temp > lx[j] + ly[k] - map[j][k])

temp = lx[j] + ly[k] - map[j][k];

for(int j = 0; j < n; ++j) //更新顶标

{

if(visitx[j])

lx[j] -= temp;

if(visity[j])

ly[j] += temp;

}

}

}

}

}

int main()

{

int ans;

while(scanf("%d", &n) != EOF)

{

ans = 0;

memset(match, -1, sizeof(match));

for(int i = 0; i < n; ++i)

for(int j = 0; j < n; ++j)

scanf("%d", &map[i][j]);

KM_perfect_match();

for(int i = 0; i < n; ++i) //权值相加

ans += map[match[i]][i];

printf("%d\n", ans);

}

return 0;

}

时间: 2024-08-11 07:44:49

http://acm.split.hdu.edu.cn/showproblem.php?pid=2255的相关文章

HDU 5652 二分加搜索 http://acm.split.hdu.edu.cn/showproblem.php?pid=5652

Problem Description A long time ago there are no himalayas between India and China, the both cultures are frequently exchanged and are kept in sync at that time, but eventually himalayas rise up. With that at first the communation started to reduce a

HDU 1285 确定比赛名次 http://acm.split.hdu.edu.cn/showproblem.php?pid=1285

Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输入有若干组,每组中的第一行为二个数N(1<=N<=500),M:其中N表示队伍的个数,M表示接着有M行的输入数据.接下来的M行数据中,每行也有两个整数P1,P2表示

HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少是多少? 因为每次相邻的交换操作最多只能减少一个逆序对,所以最多可以减少k个逆序对,所以我们只要求出原来的序列有多少个逆序对然后减去k再跟0取较大的就可以了. 因为数据范围是10的五次方,所以暴力求肯定会TLE,所以要用n*logn算法求逆序对,n*logn算法有几种可以求逆序对的: 线段树,树状数

HDU-4632 http://acm.hdu.edu.cn/showproblem.php?pid=4632

http://acm.hdu.edu.cn/showproblem.php?pid=4632 题意: 一个字符串,有多少个subsequence是回文串. 别人的题解: 用dp[i][j]表示这一段里有多少个回文串,那首先dp[i][j]=dp[i+1][j]+dp[i][j-1],但是dp[i+1][j]和dp[i][j-1]可能有公共部分,所以要减去dp[i+1][j-1]. 如果str[i]==str[j]的话,还要加上dp[i+1][j-1]+1. 但是自己却是这样想的,把每个区间都要看

http://acm.hdu.edu.cn/showproblem.php?pid=2825

地址:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题目: Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6862    Accepted Submission(s): 2279 Problem Description Liyuan lives in a

字符串处理 最佳裁判http://acm.hdu.edu.cn/showproblem.php?pid=4520

#include <stdio.h> int main() { int N; scanf("%d",&N);//先输入 double a[N],b[N],c,d=0,o[N-1],e,f;//这里定义3个数组下面会用到 for (int i=0; i<N; i++) { scanf("%lf",&a[i]); b[i]=a[i];//得到2个一样的数组,因为有一个数组因为排序要改变 } for (int i=0; i<N-1;

HDU 5547 4*4数独 http://acm.split.hdu.edu.cn/status.php

Sample Input 3 **** 2341 4123 3214 *243 *312 *421 *134 *41* **3* 2*41 4*2* Sample Output Case #1: 1432 2341 4123 3214 Case #2: 1243 4312 3421 2134 Case #3: 3412 1234 2341 4123 #include<iostream> #include<cstdio> #include<cstring> #includ

Help him http://acm.hdu.edu.cn/showproblem.php?pid=5059

题目是昨天晚上的BC.昨天晚上一直卡在第二题,囧. 今天看到题解之后,觉得自己想的也是差不多的,该考虑的也考虑到的.究竟是为什么会错.然后我就改了交,改了交.终于让我改对了一次,我找到了自己的代码中哪段有问题. 接下来上代码: wa code: int but=0; if(!sig) but=1; else but=0; long long c=0,r=1; for(int i=strlen(str)-1; i>=but; i--) { //not digit if(str[i]<'0'||s

饭卡 (背包01) http://acm.hdu.edu.cn/showproblem.php?pid=2546

/* 从一组数据中选出n个数,使这n个数的和最接近一个值x, 背包问题, 从一系列菜中,从最贵的菜(MAX)之外中选出几个菜,使菜的总价格sum最接近money-5:money-sum-MAX; 钱数相当于背包总容量,菜相当于价值和体积一样物品: */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int d