您的位置:首页 > 其它

hdu 2813 One fihgt one【KM+STLmap】

2012-12-05 13:00 387 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2813

我的链接:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=17728#problem/L

算法思想:二分图的最优匹配求最小权覆盖,吕布的战将为集合一(二分图的行),曹操的战将为集合二(二分图的列),如果两边的战将间有战争就连边,建图。

                    然后直接套模板即可。

                    题目的关键是如何输入且存储两边的战将名字,这里用到了C++中STL的map容器,水过了。PS:大牛说字典树最快。

                   STL的map:

                                          头文件#include<map>

                                                      #include<string>

                                                      using namespace std;

                                         建立容器:map<string,int> m1;

                                                             map<string,int> m2;

                                         清空容器:m1.clear();

                                                             m2.clear();

                                         进入容器:if(mi[a]==0) m1[a]=k1++; (PS :之前k1要初始化,至于是0还是1就看你自己的模板了)

                                                            或者if(mi.find(a)==m1.end()) m1[a]=k1++;也一样。

One fihgt one

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1665    Accepted Submission(s): 543


[align=left]Problem Description[/align]
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.
 

[align=left]Input[/align]
Multiple 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.
 

[align=left]Output[/align]
One integer , the least injuries Lv Bu’s generals would get.
 

[align=left]Sample Input[/align]

2 3 5
LvBu ZhangFei 6
LvBu GuanYu 5
LvBu XuChu 4
ZhangLiao ZhangFei 8
ZhangLiao XuChu 3

 

[align=left]Sample Output[/align]

8

 

[align=left]Author[/align]
shǎ崽
 

[align=left]Source[/align]
HDU 1st “Old-Vegetable-Birds
Cup” Programming Open Contest
 

[align=left]Recommend[/align]
lcy
注意:此题建立的图,不一定填满所有的边,所以开始时要把图初始化为大的负数。

             另外要注意的就是不能直接套用以前的N*N的模板了,中间相应的地方注意自己改成m,看来有必要重写模板了啊!

//Accepted 496 KB 734 ms C++ 1967 B
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<iostream>
using namespace std;
map<string,int> m1;
map<string,int> m2;
const int maxn=210;
int w[maxn][maxn];
bool s[maxn],t[maxn];
int lx[maxn],ly[maxn];
int match[maxn];
int n,m,k;

bool hungary(int u){
s[u]=true;
for(int v=1;v<=m;v++){
if(!t[v] && lx[u]+ly[v]==w[u][v]){
t[v]=true;//易遗忘
if(match[v]==-1 || hungary(match[v])){
match[v]=u;
return true;
}
}
}
return false;
}
int KM(){
int ans=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++){
lx[i]=-1<<30;//注意
}
memset(ly,0,sizeof(ly));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
lx[i]=max(lx[i],w[i][j]);
for(int i=1;i<=n;i++){
while(1){
memset(s,false,sizeof(s));
memset(t,false,sizeof(t));
if(hungary(i)) break;
else{
int a=1<<30;
for(int j=1;j<=n;j++) if(s[j]){
for(int k=1;k<=m;k++) if(!t[k] && a>lx[j]+ly[k]-w[j][k])
a=lx[j]+ly[k]-w[j][k];
}
for(int j=1;j<=n;j++){
if(s[j]) lx[j]-=a;
}
for(int j=1;j<=m;j++){
if(t[j]) ly[j]+=a;
}
}
}
}
for(int i=1;i<=m;i++) if(match[i]!=-1)//
ans+=w[match[i]][i];
return -ans;//易遗忘
}
int main(){
char name1[21],name2[21];
int u,v,injury;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
m1.clear();
m2.clear();
u=v=1;
for(int i=1;i<=n;i++){//不要忘了初始化图,因为此题不一定会填满n*m的边
for(int j=1;j<=m;j++)
w[i][j]=-1<<30;
}
while(k--){
scanf("%s%s%d",name1,name2,&injury);
if(m1.find(name1)==m1.end()) m1[name1]=u++;//若战将没有入图
if(m2.find(name2)==m2.end()) m2[name2]=v++;
w[m1[name1]][m2[name2]]=-injury;
}
printf("%d\n",KM());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: