HDU-2255 奔小康赚大钱

news/2024/7/10 5:58:24 标签: 算法, 网络, 优化

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255

解题思路:

二分图最优匹配的裸题,需要学习一下KM算法。。这道题也可以用网络流做,等学了网络流之后再写一下网络流的解题思路。

本题提供2个版本,一个是最朴素的KM算法,一个是优化后的KM算法(另外使用了输入外挂,成功刷入杭电前三大笑

代码如下:

#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;
}

优化版本:

#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 slack[N];
int match[N];
int n;

int Scan()
{
	int res = 0 , ch ;
	while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
	{
		if( ch == EOF )  return 1 << 30 ;
	}
	res = ch - '0' ;
	while( ( ch = getchar() ) >= '0' && ch <= '9' )
		res = res * 10 + ( ch - '0' ) ;
	return res ;
}

bool Hungary(int u) //匈牙利算法
{
	visitx[u] = true;
	for(int i = 0; i < n; ++i)
	{
		if(visity[i])
			continue;
		if(lx[u] + ly[i] == map[u][i])
		{
			visity[i] = true;
			if(match[i] == -1 || Hungary(match[i]))
			{
				match[i] = u;
				return true;
			}
		}
		else //不在相等子图
			slack[i] = min(slack[i], lx[u] + ly[i] - map[u][i]);
	}
	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个点匹配
	{
		for(int j = 0; j < n; ++j)
			slack[j] = INT_MAX;
		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)
					if(!visity[j])
						if(temp > slack[j])
							temp = slack[j];
				for(int j = 0; j < n; ++j) //更新顶标
				{
					if(visitx[j])
						lx[j] -= temp;
					if(visity[j])
						ly[j] += temp;
					else
						slack[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)
				map[i][j] = Scan();
		KM_perfect_match();
		for(int i = 0; i < n; ++i) //权值相加
			ans += map[match[i]][i];
		printf("%d\n", ans);
	}
	return 0;
}



http://www.niftyadmin.cn/n/1516828.html

相关文章

远程界面VNC-win/linux/

推荐使用tightvnc&#xff1a;可以下载server&#xff0c;安装在需要被远程桌面的机器上。viewer安装在当前需要看的机器上。 https://www.tightvnc.com/download-old.php ubuntu 16上安装vnc server的步骤&#xff1a; https://www.digitalocean.com/community/tutorials/how…

IClass与电源管理

前段时间为J9项目上添加电源管理&#xff0c;中间走了一些弯路。之前错误的认为&#xff0c;IClass只是与电源状态的改变方法有关&#xff0c;也就是说IClass的正确与否只会影响到设备电源状态的正确与否&#xff0c;而不会造成设备是否可以支持设备电源状态的转换。 结果后来…

Power Management

本文对Power Management这部分代码的研究是基于Wince5.0的(注&#xff1a;在最新的Wince 6.0上对电源管理的架构做了较大改变)。 这部分的代码在/PUBLIC/COMMON/OAK/DRIVERS/PM下&#xff0c;在OS中以PM.dll的形式存在。 一、PowerManagement Architecture 在/PUBLIC/COMMON/O…

python装饰器 property_Python内置装饰器@property

LeosWorkGround项目下有一个名为leo01.py的文件内容如下&#xff1a; # codingutf-8 class Student(object): def __init__(self , first_name , last_name , age , hobby): self.first_name first_name self.last_name last_name self.ageage self.hobbyhobby def __str__(s…

HDU-1533 Going Home

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1533 题目大意&#xff1a; 给你一个N行M列的矩阵&#xff0c;其中“.”代表空地&#xff0c;“H”代表房子&#xff0c;“m”代表人&#xff0c;其中有n个房子和n个人。现在要求每个人进入一间房子&#xff…

memcached分布式原理与实现

1 概况 1.1 什么是memcached memcached是一个分布式&#xff0c;开源的数据存储引擎。 memcached是一款高性能的分布式内存缓存服务器&#xff0c;通过减少查询次数来抵消沉重缓慢的数据集或API调用、提高应用响应速度、提高可扩展性。 在高并发的场景下, 大量的读/写请求涌向…

CE5 添加bsp方法

1. 解压WINCE BSP 包 到WINCE5.0安装目录下的platform目录.2. 远行Platform Builder .3. 进入File 菜单&#xff0c;选择Manage Catalog Features.4. 点击Import 按钮. 5. 根据以下路径导入BSP文件%WINCEROOT%/platform/xxxx/xxxx.cec&#xff0c;这样就引入了如上图最后一行所…

python中linspace表示什么_Python中为什么不能用可变对象作为默认参数的值

从上面代码中可以看出&#xff0c;函数的打印的是同一个列表对象numbers&#xff0c;因为他们的id值是一样的&#xff0c;只不过是列表中的元素在变化。为什么会这样呢&#xff1f;这要从函数的特性说起&#xff0c;在 Python 中&#xff0c;函数是第一类对象(function is the …