hdu3395纯KM

题意比较奇葩,就是n条鱼,相互之间在map==1时能交配生出他们val的异或值的后代,求最大后代的值。

直接套用模板。。。。这里发现之前的模板有错,所以我用这个模板重新去敲前面那题,找一下前面的错误。。。找模板真不是好习惯。。。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define INT_MAX 0x3f3f3f3f
#define INT_MIN -0x3f3f3f3f
#define MAX 105
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
int lx[MAX],ly[MAX],match[MAX],visx[MAX],visy[MAX],lack,g;
int map[MAX][MAX];
using namespace std;

int dfs(int x)
{//匈牙利
    visx[x]=1;
    for(int i=0;i<g;i++){
        if(!visy[i] && lx[x]+ly[i]==map[x][i])
        {
            visy[i]=1;
            if(match[i]==-1 || dfs(match[i]))
            {
                match[i]=x;
                return 1;
            }
        }
    }
    return 0;
}

int KM()
{
    int i,j,k;
    for(i=0;i<g;i++)
    {//初始化顶标
        lx[i]=INT_MIN; ly[i]=0;
        for(j=0;j<g;j++)
            lx[i]=max(map[i][j],lx[i]);
    }
    memset(match,-1,sizeof(match));
    for(i=0;i<g;i++)
    {
        while(1){//直到每个点都成功匹配,才结束循环
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(dfs(i))break; //如果点 i 成功匹配,则不需要调整定标值

            /*------------顶标调整------------*/
            int lack=INT_MAX;//顶标调整值
            for(j=0;j<g;j++)
            {
                if(visx[j])
                {
                    for(k=0;k<g;k++)
                    {//取幅度最小的值为调整值
                        if(!visy[k])lack=min(lx[j]+ly[k]-map[j][k],lack);
                    }
                }
            }
            for(j=0;j<g;j++){//调整已经得到匹配的点对的顶标值
                if(visx[j])lx[j]-=lack;
                if(visy[j])ly[j]+=lack;
            }
            /*---------------------------------*/
        }
    }
    int sum=0;
    for(i=0;i<g;i++)
    {
        if(match[i]!=-1)
            sum+=map[match[i]][i];
    }
    return sum;
}
int main()
{
    int n,i,j;
    char ch;
    int value[MAX];
    while(cin>>n)
    {
  memset(map,0,sizeof(map));
        if(n==0)break;
        for(i=0;i<n;i++)
            cin>>value[i];
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
            {
                cin>>ch;
                if(ch=='1')
                {

     //cout<<value[i]<<" "<<value[j]<<endl;
                    map[i][j]=value[i]^value[j];
    // cout<<map[i][j]<<endl;
     //cout<<" **********"<<endl;
                }
            }
 /* for(i=0;i<n;i++)
   {
    //cout<<endl;
            for(j=0;j<n;j++)
    cout<<map[i][j]<<" ";
   }*/
            g=n;
            int res=KM();
            cout<<res<<endl;

    }
    return 0;
}


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值