程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 2853

hdu 2853

編輯:C++入門知識

虛擬賽一開始lyf就對我說這是一道匹配的題目,我一看明顯裸的最優匹配,敲完提交wrong,

題目要求改變盡量少的公司,就是如果遇到相等的權值,優先選擇跟他原來匹配的,KM匹配是按序號大小來的,如果一個公司原來匹配的序號較大,前面有權值相等的點時,KM就會選擇前面的點參加匹配。想了好長時間不知道怎麼去優先選擇原來匹配的邊,

最後想著如果把原來匹配的邊變得大一些的話,就可以,但是變大的話就會影響最優匹配的總值,而且變大的話還會影響原來比他大的權值,所以就是所有的權值都得擴大,我想到的是都*100,原來匹配的邊再加1,因為最多選50條邊,也就是最多有50個01相加,不會超過一百,得到的答案除以一百,就把加的1都去掉了,只要擴大的倍數大於n就可以,,

 

#include<stdio.h>
#include<string.h>
#define N 55
#define inf 0x3fffffff
int map[N][N],lx[N],ly[N],sx[N],sy[N],d[N],n,m,match[N],Kmatch[N],tch[N];
int find(int x)
{
    sx[x]=1;
    for(int i=1;i<=m;i++)
    {
        if(sy[i]==1)continue;
        int temp=lx[x]+ly[i]-map[x][i];
        if(temp==0)
        {
            sy[i]=1;
            if(match[i]==-1||find(match[i])==1)
            {
                match[i]=x;
                Kmatch[x]=i;
                return 1;
            }
        }
        else d[i]=d[i]>temp?temp:d[i];
    }
    return 0;
}
int KM()
{
    int i,j,k,min,sum;
    memset(ly,0,sizeof(ly));
    memset(match,-1,sizeof(match));
    memset(Kmatch,-1,sizeof(Kmatch));
    for(i=1;i<=n;i++)
    {
        lx[i]=map[i][1];
        for(j=2;j<=m;j++)
            if(lx[i]<map[i][j])
                lx[i]=map[i][j];
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
            d[j]=inf;
        while(1)
        {
            memset(sx,0,sizeof(sx));
            memset(sy,0,sizeof(sy));
            if(find(i)==1)break;
            min=inf;
            for(k=1;k<=m;k++)
                if(sy[k]==0&&min>d[k])
                    min=d[k];
            for(j=1;j<=n;j++)
                if(sx[j]==1)lx[j]-=min;
            for(j=1;j<=m;j++)
                if(sy[j]==1)ly[j]+=min;
        }
    }
    sum=0;
    for(i=1;i<=n;i++)
        sum+=map[i][Kmatch[i]];
    return sum;
}
int main()
{
    int i,j,k,ans,sum;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                map[i][j]=-inf;
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                scanf("%d",&map[i][j]);
                map[i][j]*=100;
            }
        ans=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&k);
            tch[i]=k;
            ans+=map[i][k];
            map[i][k]++;
        }
        ans/=100;
        sum=KM()/100;
        k=0;
        for(i=1;i<=n;i++)
            if(tch[i]!=Kmatch[i])
                k++;
        printf("%d %d\n",k,sum-ans);
    }
    return 0;
}

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved