<题意:两个部队对打,输入A方对B方某人要损伤的数据,求损伤最少要多少?
输入:
LvBu ZhangFei 6
LvBu GuanYu 5
LvBu XuChu 4
ZhangLiao ZhangFei 8
ZhangLiao XuChu 3
输出:8
题解:求最大匹配下的最少损伤数,完备匹配的最大权匹配,(求负数既可以得到最少)
# include <iostream>
# include<stdio.h>
# include<string.h>
# include<map>
# include<vector>
# include<algorithm>
using namespace std;
const int N = 205;
const int inf = -1e9;
int mapp[N][N], lx[N], ly[N];
int visitx[N], visity[N], link[N];
int n, m;
bool hungery(int cur)
{
visitx[cur] = 1;
for(int i = 1; i <= m; i ++)
{
if(visity[i] == 0 && lx[cur] + ly[i] == mapp[cur][i])
{
visity[i] = 1;
if(link[i] == 0 || hungery(link[i]))
{
link[i] = cur;
return true;
}
}
}
return false;
}
void km()
{
for(int i = 1; i <= n; i ++)
lx[i] = inf;
memset(ly, 0, sizeof(ly));
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
lx[i] = max(lx[i], mapp[i][j]);
memset(link, 0, sizeof(link));
for(int k = 1; k <= n; k ++)
{
while(1)
{
memset(visitx, 0, sizeof(visitx));
memset(visity, 0, sizeof(visity));
if(hungery(k))
break;
else
{
int temp = - inf;
for(int i = 1; i <= n; i ++)
if(visitx[i])
for(int j = 1; j <= m; j ++)
if(!visity[j] && temp > lx[i] + ly[j] - mapp[i][j])
temp = lx[i] + ly[j] - mapp[i][j];
for(int i = 1; i <= n; i ++)
if(visitx[i])
lx[i] -= temp;
for(int i = 1; i <= m; i ++)
if(visity[i])
ly[i] += temp;
}
}
}
}
int main()
{
int k;
map<string, int >l;
map<string, int >c;
while(~scanf("%d%d%d", &n, &m, &k))
{
int num1 = 1;
int num2 = 1;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
mapp[i][j] = inf;
l.clear();
c.clear();
for(int i = 0; i < k; i ++)
{
char a[25], b[25];
int x;
scanf("%s%s%d", a, b, &x);
if(!l[a])
l[a] = num1++;
if(!c[b])
c[b] = num2++;
mapp[l[a]][c[b]] = -x;
//cout<<mapp[l[a]][c[b]]<<" ";
}
km();
int ans = 0;
for(int i = 1; i <= m; i ++)
{
if(link[i])
ans += mapp[link[i]][i];
}
printf("%d\n", - ans);
}
return 0;
}