HDU 2426 Interesting Housing Problem

赤裸裸的带权最大匹配

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. #define MAXN 505
  5. #define inf 2000000000
  6. #define _clr(x) memset(x,0xff,sizeof(int)*n)
  7. int mat[MAXN][MAXN],n,m,match1[MAXN], match2[MAXN];
  8. bool map[MAXN][MAXN];
  9. int kuhn_munkras(int n, int m){
  10.     int s[MAXN],t[MAXN],l1[MAXN],l2[MAXN],p,q,ret=0,i,j,k;
  11.     for (i=0;i<m;i++)
  12.         for (l1[i]=-inf,j=0;j<n;j++)
  13.             l1[i]=mat[i][j]>l1[i]?mat[i][j]:l1[i];
  14.     for (i=0;i<n;l2[i++]=0);
  15.     for (_clr(match1),_clr(match2),i=0;i<m;i++){
  16.         for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)
  17.             for (k=s[p],j=0;j<n&&match1[i]<0;j++)
  18.                 if (l1[k]+l2[j]==mat[k][j]&&t[j]<0){
  19.                     s[++q]=match2[j],t[j]=k;
  20.                     if (s[q]<0)
  21.                         for (p=j;p>=0;j=p)
  22.                             match2[j]=k=t[j],p=match1[k],match1[k]=j;
  23.                 }
  24.         if (match1[i]<0){
  25.             for (i--,p=inf,k=0;k<=q;k++)
  26.                 for (j=0;j<n;j++)
  27.                     if (t[j]<0&&l1[s[k]]+l2[j]-mat[s[k]][j]<p)
  28.                         p=l1[s[k]]+l2[j]-mat[s[k]][j];
  29.             for (j=0;j<n;l2[j]+=t[j]<0?0:p,j++);
  30.             for (k=0;k<=q;l1[s[k++]]-=p);
  31.         }
  32.     }
  33.     for (i=0;i<m;i++)
  34.         ret+=mat[i][match1[i]];
  35.     return ret;
  36. }
  37. bool DEBUG=false;
  38. int main()
  39. {
  40.     int t,x,y,len,i,j,k,ans,id=0;
  41.     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
  42.     {
  43.         for(i=0;i<n;i++)for(j=0;j<m;j++)mat[i][j]=-inf;
  44.         memset(map,false,sizeof(map));
  45.         while(k--)
  46.         {
  47.             scanf("%d%d%d",&x,&y,&len);
  48.             if(len<0)continue;
  49.             mat[x][y]=len;
  50.             map[x][y]=true;
  51.         }
  52.         printf("Case %d: ",++id);
  53.         if(n>m)
  54.         {
  55.             printf("-1/n");
  56.             continue;
  57.         }
  58.         ans=kuhn_munkras(m,n);
  59.         for(i=0;i<n;i++)if(!map[i][match1[i]])break;
  60.         printf("%d/n",i==n?ans:-1);
  61.     }
  62.     return 0;
  63. }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值