題意:呂布有 n 個武将 對戰 曹操 m 個武将 (n<=m),并給出 k 個對戰的戰力損耗值,求呂布方的最優戰對比對,使得戰力損耗值最小,隻能一對一;(呂布的每個武将都必須戰鬥一場)
分析:KM比對裸題,武将名字用 map 标序就行了;
代碼:
#include<map>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN = 200+2;
const int INF = 0X3F3F3F3F3F;
int love[MAXN][MAXN];
int ex_girl[MAXN];
int ex_boy[MAXN];
bool vis_girl[MAXN];
bool vis_boy[MAXN];
int match[MAXN];
int ans[MAXN];
int slack[MAXN];
int n,N,e;
bool dfs(int girl)
{
vis_girl[girl]=true;
for(int boy=0;boy<N;boy++)
{
if(vis_boy[boy]) continue;
int gap=ex_girl[girl]+ex_boy[boy]-love[girl][boy];
if(gap==0)
{
vis_boy[boy]=true;
if(match[boy]==-1||dfs(match[boy]))
{
match[boy]=girl;
ans[girl]=boy;
return true;
}
}
else
{
slack[boy]=min(slack[boy],gap);
}
}
return false;
}
int KM(int tot)
{
memset(ans,-1,sizeof(ans));
memset(match,-1,sizeof(match));
memset(ex_boy,0,sizeof(ex_boy));
for(int i=0;i<N;i++)
{
ex_girl[i]=love[i][0];
for(int j=0;j<N;j++)
ex_girl[i]=max(ex_girl[i],love[i][j]);
}
for(int i=0;i<N;i++)
{
fill(slack,slack+N,INF);
while(1)
{
memset(vis_girl,false,sizeof(vis_girl));
memset(vis_boy,false,sizeof(vis_boy));
if(dfs(i)) break;
int d=INF;
for(int j=0;j<N;j++)
if(!vis_boy[j]) d=min(d,slack[j]);
for(int j=0;j<N;j++)
{
if(vis_girl[j]) ex_girl[j]-=d;
if(vis_boy[j])
ex_boy[j]+=d;
else
slack[j]-=d;
}
}
}
int res=0;
for(int i=0;i<tot;i++) res+=love[i][ans[i]];
return res;
}
int main()
{
ios::sync_with_stdio(false);
map<string,int>ft,sd;
while(cin>>n>>N>>e)
{
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
love[i][j]=-INF;
ft.clear();
sd.clear();
string a,b;
int num,pre=0,suf=0;
while(e--)
{
cin>>a>>b>>num;
if(ft[a]==0) ft[a]=(++pre);
if(sd[b]==0) sd[b]=(++suf);
love[ft[a]-1][sd[b]-1]=-num;
}
cout<<-KM(n)<<'\n';
}
}