题目链接: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
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.
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.
2 3 5 LvBu ZhangFei 6 LvBu GuanYu 5 LvBu XuChu 4 ZhangLiao ZhangFei 8 ZhangLiao XuChu 3
8
另外要注意的就是不能直接套用以前的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; }