zoukankan      html  css  js  c++  java
  • 奔小康赚大钱---hdu2255(最大带权匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255

    带权匹配问题的模板;

    运用KM算法;

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #define INF 0xfffffff
    #define N 330
    using namespace std;
    
    int maps[N][N], visx[N], visy[N], used[N], lx[N], ly[N], s[N], n;
    ///visx[i]代表第i人是否在曾广路上,
    ///used[i]代表第i个村庄是否被占用;
    ///lx[],ly[]代表人和村庄的顶标;
    bool Find(int u)
    {
        visx[u] = 1;
        for(int i=1; i<=n; i++)
        {
            if(!visy[i] && lx[u]+ly[i] == maps[u][i])
            {
                visy[i] = 1;
                if(!used[i] || Find(used[i]))
                {
                    used[i]=u;
                    return true;
                }
            }
            else
            {
                s[i] = min(s[i], lx[u]+ly[i] - maps[u][i]);
            }
        }
        return false;
    }
    int KM()
    {
        memset(used, 0, sizeof(used));
        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(maps[i][j], lx[i]);///初始化人的顶标;
        }
        for(int i=1; i<=n; i++)///寻找最大匹配;人
        {
            for(int j=1; j<=n; j++)
                s[j]=INF;
            while(1)
            {
                memset(visx, 0, sizeof(visx));
                memset(visy, 0, sizeof(visy));
                if(Find(i))///找到的曾广路就退出,否则改变顶标,找到为止;
                    break;
                int d = INF;
                for(int j=1; j<=n; j++)
                {
                    if(!visy[j])
                        d=min(d, s[j]);
                }
                for(int j=1; j<=n; j++)
                {
                    if(visx[j])
                        lx[j]-=d;
                    if(visy[j])
                        ly[j]+=d;
                }
            }
        }
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            ans+=maps[used[i]][i];
        }
        return ans;
    }
    
    int main()
    {
        while(scanf("%d", &n)!=EOF)
        {
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                    scanf("%d", &maps[i][j]);
            }
            printf("%d
    ", KM());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    装饰者模式
    代理模式
    享元模式
    模板模式
    命令模式
    建造者模式
    单例模式
    观察者模式
    迭代器模式
    访问者模式
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4717717.html
Copyright © 2011-2022 走看看