完备匹配下的最大权匹配

<题意:两个部队对打,输入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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值