HDU 2813 One fihgt one map+最大匹配值

本篇介绍了一个基于二分匹配算法的战争模拟问题,吕布与曹操的大将们如何通过最优匹配策略减少战斗中的伤害。使用了图论中的经典算法解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击打开链接

One fihgt one

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1968    Accepted Submission(s): 638



Problem Description
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.
 

Input
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.
 

Output
One integer , the least injuries Lv Bu’s generals would get.
 

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

Sample Output
    
8
 

Author
shǎ崽
 

Source
 

Recommend
lcy

题意是说吕布要和曹操打仗,吕布手下有n元大将,曹操手下有m元大将,有k场战役,每场战役吕布派一名大将跟曹操的一名大将单挑,并且给你耗血量,让你求吕布军所有大将耗血量最低。
二分匹配求最大匹配值,用map来标记,968秒过。


#include<stdio.h>
#include<string.h>
#include<string>
#include<map>
#define M 207
#define inf 1<<30
using namespace std;
int lx[M],ly[M],g[M][M];
int slack[M],match[M];
bool visx[M],visy[M];
int n,m,k;
bool dfs(int cur)
{
    visx[cur]=true;
    for(int y=1; y<=m; y++)
    {
        if(!visy[y]&&lx[cur]+ly[y]==g[cur][y])
        {
            visy[y]=true;
            if(match[y]==-1||dfs(match[y]))
            {
                match[y]=cur;
                return true;
            }
        }
//        else if(slack[y]>t)
//            slack[y]=t;
    }
    return false;
}
void KM()
{
    memset(match,-1,sizeof(match));
    memset(ly,0,sizeof(ly));
    for(int i=1; i<=n; i++)
    {
        lx[i]=-inf;
        for(int j=1; j<=m; j++)
            lx[i]=max(lx[i],g[i][j]);
    }
    for(int x=1; x<=n; x++)
    {
//        for(int i=1; i<=m; i++)
//            slack[i]=inf;
        while(true)
        {
            memset(visx,false,sizeof(visx));
            memset(visy,false,sizeof(visy));
            if(dfs(x))break;
            int d=inf;
            for(int j=1;j<=n;j++)
                if(visx[j])
                {
                    for(int k=1;k<=m;k++)
                    {
                        if(!visy[k]&&d>lx[j]+ly[k]-g[j][k])
                        {
                            d=lx[j]+ly[k]-g[j][k];
                        }
                    }
                }
//            for(int i=1; i<=m; i++)
//                if(!visy[i]&&d>slack[i])
//                    d=slack[i];
//            if(d==inf)return ;
            for(int i=1; i<=n; i++)
                if(visx[i])
                    lx[i]-=d;
            for(int i=1; i<=m; i++)
                if(visy[i])
                    ly[i]+=d;
//                else
//                    slack[i]-=d;
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        char s1[22],s2[22];
        int a,num1=1,num2=1;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                g[i][j]=-inf;

        map<string,int>mp1,mp2;
        for(int i=1; i<=k; i++)
        {
            scanf("%s%s%d",s1,s2,&a);
            if(!mp1[s1])
            {
                mp1[s1]=num1++;
            }
            if(!mp2[s2])
            {
                mp2[s2]=num2++;
            }
            g[mp1[s1]][mp2[s2]]=-a;
        }
        KM();
        int result=0;
        for(int i=1; i<=m; i++)
        {
            if(match[i]!=-1&&g[match[i]][i]!=-inf)
                result+=g[match[i]][i];
        }
        printf("%d\n",-result);
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值