zoukankan      html  css  js  c++  java
  • hdu2255二分最优匹配KM标准模板

    其实与今天做的强连通那倒模板题一样,代码不能完全理解,到学会了如何判断是否能用km模板来做,而且也学会了套用km模板来ac了,但是原理却还是不太清楚,果然还是要继续慢慢想明白才行啊,先贴出模板吧,明天再做一下km,继续理解下去。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define CLR(arr, what) memset(arr, what, sizeof(arr))
    #define maxn  305
    #define INF  (1<<30)-1
    int g[maxn][maxn];
    int lx[maxn],ly[maxn],match[maxn];
    bool visx[maxn],visy[maxn];
    int slack[maxn];
    int n,m;
    bool dfs(int cur){
         visx[cur] = true;
         for(int y=1;y<=m;y++){
             if(visy[y])   continue;
             int t=lx[cur]+ly[y]-g[cur][y];
             if(t==0){
                visy[y] = true;
                if(match[y]==-1||dfs(match[y])){
                    match[y] = cur;
                    return true;
                }
             }
             else if(slack[y]>t){
                     slack[y]=t;
             }
         }
         return false;
    }
    int KM(){
        CLR(match,-1);
        CLR(ly,0);;
        for(int i=1 ;i<=n;i++){
             lx[i]=-INF;
           for(int j=1;j<=m;j++)
               if(g[i][j]>lx[i])   lx[i]=g[i][j];
       }
       for(int x=1;x<=n;x++){
            for(int i=1;i<=m;i++)  slack[i]=INF;
            while(true){
                CLR(visx,false);
                CLR(visy,false);
                if(dfs(x))  break;
                int d=INF;
                for(int i=1;i<=m;i++){
                   if(!visy[i]&&d>slack[i])     d=slack[i];
                }
                for(int i=1;i<=n;i++){
                   if(visx[i])                  lx[i]-=d;
                }
                for(int i=1;i<=m;i++){
                   if(visy[i])                 ly[i]+=d;
                   else                        slack[i]-=d;
                }
            }
       }
        int result = 0;
        for(int i = 1; i <=m; i++)
        if(match[i]!=-1)
            result += g[match[i]][i];
        return result;
    }
    int main(){
        while(scanf("%d",&n)!=EOF){
            CLR(g,0);
            m=n;
            for(int i = 1; i <=n; i++)
            for(int j = 1; j <=m; j++)
            {
                scanf("%d",&g[i][j]);
            }
                /*for(int i=1;i<=n;i++)
                {
                    cout<<endl;
                    for(int j=1;j<=m;j++)
                    cout<<g[i][j]<<" ";
                }*/
                printf("%d\n",KM());
        }
        return 0;
    }
    
     
  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134179.html
Copyright © 2011-2022 走看看