HDU2255 奔小康赚大钱

二分图完美匹配

题目传送门

完美匹配模板题,注意包含多组数据。

贴上代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;
int cost[305][305];
int who[305];
int lx[305],ly[305],slack[305];
bool f[305],s[305];
bool dfs(int i){
    s[i]=true;
    for (int j=1;j<=n;j++){
        if (f[j])
            continue;
        int pd=lx[i]+ly[j]-cost[i][j];
        if (!pd){
            f[j]=true;
            if (!who[j]||dfs(who[j])){
                who[j]=i;
                return true;
            }
        }
        else
            slack[j]=min(slack[j],pd);
    }
    return false;
}
int main(){
    while (scanf("%d",&n)==1){
        memset(cost,0,sizeof(cost));
        memset(ly,0,sizeof(ly));
        memset(lx,0,sizeof(lx));
        memset(who,0,sizeof(who));
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                scanf("%d",&cost[i][j]);
            }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                lx[i]=max(lx[i],cost[i][j]);
        for (int i=1;i<=n;i++){
            memset(slack,0x7f,sizeof(slack));
            while (1){
                memset(s,false,sizeof(s));
                memset(f,false,sizeof(f));
                if (dfs(i))
                    break;
                int m=0x7fffffff;
                for (int j=1;j<=n;j++)
                    if (!f[j])
                        m=min(m,slack[j]);
                for (int j=1;j<=n;j++){
                    if (s[j])
                        lx[j]-=m;
                    if (f[j])
                        ly[j]+=m;
                    else slack[j]-=m;
                }
            }
        }
        int ans=0;
        for (int i=1;i<=n;i++)
            ans+=cost[who[i]][i];
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值