HDU 2813 One fihgt one(KM算法解决最小权值匹配)

One fihgt one
Lv Bu and his soldiers are facing a cruel war——Cao Cao had his best generals just miles away. 
 
There’s little time , but Lv Bu is unaware of how to arrange his warriors , what he know is that he have n brave generals while Cao Cao has m , and he has k fights to choose from , he’d like to make all his n warriors participate in the battle but get the least injuries . Lv Bu is happy because there is always a good solution . So , now is your task to tell Lv Bu the least injuries his troop would get. 
No one could take part in two fights.
InputMultiple cases. For each case ,there are three integers in the first line , namely n,m (1<=n<=m<=200)and k (n<=k<=m*n). 
The next k lines are the information about k possible fights , for each line are two strings (no more than 20 characters ) and an integer. The first string indicates Lv Bu’s general and the second , of course , Cao Cao’s , and the integer is the injury Lv Bu’s general would get if this fight were chosen. OutputOne integer , the least injuries Lv Bu’s generals would get. Sample Input
2 3 5
LvBu ZhangFei 6
LvBu GuanYu 5
LvBu XuChu 4
ZhangLiao ZhangFei 8
ZhangLiao XuChu 3

Sample Output

8

题目意思说吕布和曹操两军对垒,现在派将军就叫阵。吕布一方有N个将军,曹操一方有M个将军。然后有K个关系,每个关系由3元描述,吕布一方的将军名字,曹操一方的将军名字,如果两者对战将会损失X点血量。

现在问吕布一方在尽可能出战的情况下(别人来叫阵不能不出)损失的最小血量。


那么这个就有点像二分图匹配了,而且是带边权的二分图匹配。

左边是吕布的将军,右边是曹操的将军。现在要损失的血量最小,那么就找边权最小的将军对战(挑软柿子捏)


求二分图最大边权匹配我们有KM算法,现在使求二分图最小边权匹配。

其实只需要在KM算法上改一点就可以。把每条边的边权改为负值。

这样求出来的答案就是负值,且是所有可能中负值最大一个。

在去负值,那就是最小了,此时答案就是所有可能中最小的一个。也就是最小边权匹配。


有一道类似的题目,大家可以也可以看看点我传送 (๑ •̀ㅂ•́) ✧


#include<iostream>
#include<cstdio>
#include<cstring>
#include<functional>
#include<algorithm>
#include<map>
#define maxn 240
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k;
map<string,int>mapsx,mapsy;
int link[maxn][maxn];
int match[maxn];
int slack[maxn];
bool visx[maxn],visy[maxn];
int ex[maxn],ey[maxn];
bool dfs(int x)
{
	visx[x]=1;
	for(int y=1;y<=m;y++)
	{
		if(visy[y])
			continue;
		int gap=ex[x]+ey[y]-link[x][y];
		if(gap==0)
		{
			visy[y]=1;
			if(match[y]==0||dfs(match[y]))
			{
				match[y]=x;
				return 1;
			}
		}
		else
			slack[y]=min(slack[y],gap);
	}
	return 0;
}

int KM()
{
	int i,j;
	memset(ex,0,sizeof(ex));
	memset(ey,0,sizeof(ey));
	memset(match,0,sizeof(match));
	for(i=1;i<=n;i++)
	{
		ex[i]=link[i][1];
		for(j=2;j<=m;j++)
			ex[i]=max(ex[i],link[i][j]);
	}
	for(i=1;i<=n;i++)
	{
		memset(slack,0x3f,sizeof slack);//fill(slack,slack+m+1,inf);
		while(1)
		{
			memset(visx,0,sizeof(visx));
			memset(visy,0,sizeof(visy));
			if(dfs(i))
				break;
			else
			{
			int d=inf;
			for(j=1;j<=m;j++)
				if(!visy[j])
					d=min(d,slack[j]);
			for(j=1;j<=n;j++)
				if(visx[j])
					ex[j]-=d;
			for(j=1;j<=m;j++)
				if(visy[j])
					ey[j]+=d;
				else
					slack[j]-=d;
			}
		}
	}
	int sum=0;
	for(i=1;i<=m;i++)
		sum+=link[match[i]][i];
	return sum;
}

int main()
{
	int i,j,cntx,cnty,c;
	int ans;
	char a[30],b[30];
	while(scanf("%d%d%d",&n,&m,&k)!=EOF)
	{
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
				link[i][j]=-inf;//初始化地图,应该初始化为-inf
		}//开始初始化为0错了好久
		cntx=cnty=1;
		for(i=1;i<=k;i++)
		{
			scanf("%s%s%d",&a,&b,&c);
			if(mapsx.find(a)==mapsx.end())//把人名映射
				mapsx[a]=cntx++;
			if(mapsy.find(b)==mapsy.end())
				mapsy[b]=cnty++;
			link[mapsx[a]][mapsy[b]]=-c;
		}
		ans=KM();//二分图最大权值匹配
		printf("%d\n",-ans);
	}
}


全部评论

相关推荐

点赞 评论 收藏
分享
04-03 09:32
已编辑
华南农业大学 golang
我的代码出BUG了:"晚点发个邮件调整一下时间",你收到新的邮件没,如果没有收到新的邮件,那就需要进入面试链接留痕,否则系统会判定你迟到
点赞 评论 收藏
分享
05-04 09:38
已编辑
门头沟学院 引擎开发
个人9本海硕,本硕期间一直在投游戏相关实习/校招,岗位由客户端-&gt;引擎-&gt;TA-&gt;AIGC。最终目标肯定是独游制作人,所以程序策划美术都点了些,感觉也没谁了。值此春招末尾总结下技术向校招要点,算是回馈牛客社区了。也附上我的Github和个人博客,欢迎各种交流讨论。&nbsp;前言&nbsp;首先是个人惯例的劝退游戏行业。参见缅怀故人&nbsp;和永远有多远&nbsp;,相比于互联网,游戏薪资大概相当但要求更高,加班严重且更为局限。如果你只是带着一腔热情想入这行,建议先找个日常实习了解下真实的游戏行业再做选择。&nbsp;准备&nbsp;当然,在你决定踏出这步后,第一步就是准备相关的笔试面试。这里先建议找到你感兴趣的公司岗位的JD,然后...
牛客28967172...:说的还是有道理的,我校招时就拿到过网易雷火好几个顶级项目组方向的offer,基本上流程和你说的一样。 但本质还是劝退互联网的游戏方向,本质上是代价更高,而且职业生涯容错率很低,方向比较窄。 代价是众所周知的严重加班,游戏大版本赶工基本上通宵无休,甚至国庆五一都没放假是常态。 职业生涯性价比低是因为游戏行业本质上就是赢家通吃,但你要跳槽只有腾讯网易等头部,要么就是米哈游莉莉丝库洛三七等少数中厂,然后就没了,公司是断崖的少 游戏开发相比互联网方向岗位非常非常少,比如网易整个雷火也才五六百人,里面十几个工作室,招人比例非常低,其他游戏公司也是一样。 而且方向也很窄,你做引擎开发就只能跳相关,你做游戏客户端也只能跳相关(游戏客户端都算吃香的,但市场hc也非常非常少,跳槽机会更少),基本上很难转回互联网 这里对比传统互联网,大厂多的都说不过来,而且容错率很大,你做搜索方向可以跳推荐,你做推荐方向可以跳广告,要求远没有游戏行业那么严,甚至你之前干测试都能跳槽研发方向
我的求职进度条
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务