zoukankan      html  css  js  c++  java
  • poj2195

    题解:

    简单KM

    把每一个男的和房子分离

    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int NN=1005,MM=10005;
    int a[NN][NN],v[NN][NN],g[NN][NN],lk[MM],lx[MM],ly[MM];
    int visx[MM],visy[MM],slack[MM],N,M,n,n1,n2,cnt,ans;
    int dfs(int x)
    {
        visx[x]=cnt;
        for (int y=1;y<=n;y++)
         {
            if (visy[y]==cnt) continue;
            int t=lx[x]+ly[y]-g[x][y];
            if (!t)
             {
                 visy[y]=cnt;
                if (!lk[y]||dfs(lk[y])){lk[y]=x;return 1;}
             }
            else if (slack[y]>t) slack[y]=t;
         }
        return 0;
    }
    void KM()
    {
        memset(lk,0,sizeof(lk));
        memset(lx,0,sizeof(lx));
        memset(ly,0,sizeof(ly));
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++)lx[i]=max(lx[i],g[i][j]);
        for (int x=1;x<=n;++x)
         {
            for (int i=1;i<=n;i++)slack[i]=1e9;
            while (cnt++,!dfs(x))
             {
                int d=1e9;
                for (int i=1;i<=n;i++)
                 if (visy[i]!=cnt) d=min(d,slack[i]);
                for (int i=1;i<=n;i++)
                 {
                    if (visx[i]==cnt) lx[i]-=d;
                    if (visy[i]==cnt) ly[i]+=d;
                    else slack[i]-=d;
                 }
              }
         }
        return;
    }
    void work()
    {
        n1=n2=ans=0;
        for (int i=1;i<=N;i++)
         for (int j=1;j<=M;j++)
          {
            for (a[i][j]=getchar();a[i][j]!='.'&&a[i][j]!='m'&&a[i][j]!='H';a[i][j]=getchar());
            if (a[i][j]=='m') v[i][j]=++n1;
            if (a[i][j]=='H') v[i][j]=++n2;
         }
        for (int i=1;i<=N;i++)
         for (int j=1;j<=M;++j)
          {
            if (a[i][j]!='m') continue;
            for (int p=1;p<=N;p++)
             for (int q=1;q<=M;q++)
                if (a[p][q]=='H') g[v[i][j]][v[p][q]]=-abs(i-p)-abs(j-q);
          }
        n=n1;
        KM();
        for (int i=1;i<=n;i++)ans+=lx[i]+ly[i];
        printf("%d
    ",-ans);
        return;
    }
    int main()
    {
        while (~scanf("%d%d",&N,&M)&&N|M) work();
        return 0;
    }
  • 相关阅读:
    HDU1398Square Coins(母函数)
    HDU2079选课时间(母函数)
    HDU1028Ignatius and the Princess III(母函数)
    POJ1061青蛙的约会(扩展欧几里得)
    POJ1189钉子和小球(DP)
    POJ1179Polygon(DP)
    POJ2001Shortest Prefixes(字典树)
    POJ1157 LITTLE SHOP OF FLOWERS
    POJ3630Phone List(字典树)
    亲和串(HDU2203)
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8289436.html
Copyright © 2011-2022 走看看