zoukankan      html  css  js  c++  java
  • P

    分析:这是一个KM的模板题,也就不多说了,KM最复杂的情况都能过,下面是没有优化过的代码:
    ************************************************************
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;

    const int MAXN = 305;
    const int oo = 1e9+7;

    int w[MAXN][MAXN], N;
    int dx[MAXN], dy[MAXN];
    int Ly[MAXN], slack[MAXN];
    bool vx[MAXN], vy[MAXN];

    bool Find(int i)
    {///别忘记vx[i]赋值true,表示可以增广的时候达到了i点
        vx[i] = true;
        for(int j=1; j<=N; j++)
        {
            if( !vy[j] && dx[i]+dy[j] == w[i][j] )
            {
                vy[j] = true;

                if( !Ly[j] || Find(Ly[j]) )
                {
                    Ly[j] = i;
                    return true;
                }
            }
            ///else if(vy[j] == false)
               
    /// slack[j] = min(slack[j], dx[i]+dy[j]-w[i][j]);
        }

        return false;
    }
    int KM()
    {
        int i, j, k;

        for(i=1; i<=N; i++) while(1)
        {///给每个点进行增广,找不到减去一个d,继续找

            memset(vx, falsesizeof(vx));
            memset(vy, falsesizeof(vy));

            if( Find(i) == truebreak;

            int d = oo;

            for(j=1; j<=N; j++) if( vx[j] )
            for(k=1; k<=N; k++) if( !vy[k] )
            {///用访问过的左边和未访问过的右边求出来一个最小的d
                d = min( d,  dx[j]+dy[k]-w[j][k]);
            }

            for(j=1; j<=N; j++)
            {///左边的标杆减去d,右边的加上d,这样原来匹配的值没有改变
             
    ///减去d的目的是为了查找那个可以增广的边里面最大的那个
                if(vx[j])dx[j] -= d;
                if(vy[j])dy[j] += d;
            }
        }

        int sum = 0;

        for(i=1; i<=N; i++)
        {
            sum += w[ Ly[i] ][i];
        }

        return sum;
    }

    int main()
    {
        while(scanf("%d", &N) != EOF)
        {
            memset(dx, falsesizeof(dx));
            memset(dy, falsesizeof(dy));
            memset(Ly, falsesizeof(Ly));

            for(int i=1; i<=N; i++)
            for(int j=1; j<=N; j++)
            {
                scanf("%d", &w[i][j]);
                dx[i] = max(dx[i], w[i][j]);
            }

            printf("%d ", KM());
        }

        return 0;
    }
    View Code
    *********************************************************************
    下面是优化过的,感觉时间上减少的不是那么明显,少了100多ms
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;

    const int MAXN = 305;
    const int oo = 1e9+7;

    int w[MAXN][MAXN], N;
    int dx[MAXN], dy[MAXN];
    int Ly[MAXN], slack[MAXN];
    bool vx[MAXN], vy[MAXN];

    bool Find(int i)
    {///别忘记vx[i]赋值true,表示可以增广的时候达到了i点
        vx[i] = true;
        for(int j=1; j<=N; j++)
        {
            if( !vy[j] && dx[i]+dy[j] == w[i][j] )
            {
                vy[j] = true;

                if( !Ly[j] || Find(Ly[j]) )
                {
                    Ly[j] = i;
                    return true;
                }
            }
            else if(vy[j] == false)
                slack[j] = min(slack[j], dx[i]+dy[j]-w[i][j]);
        }

        return false;
    }
    int KM()
    {
        int i, j;

        for(i=1; i<=N; i++)
        {
            for(j=1; j<=N; j++)
                slack[j] = oo;

            while(true)
            {
                memset(vx, falsesizeof(vx));
                memset(vy, falsesizeof(vy));

                if( Find(i) == true )break;

                int d = oo;

                for(j=1; j<=N; j++)
                {
                    if(!vy[j] && d > slack[j])
                        d = slack[j];
                }

                for(j=1; j<=N; j++)
                {
                    if(vx[j])dx[j] -= d;
                    if(vy[j])dy[j] += d;
                    else slack[j] -= d;
                }
            }
        }

        int sum = 0;

        for(i=1; i<=N; i++)
        {
            sum += w[ Ly[i] ][i];
        }

        return sum;
    }

    int main()
    {
        while(scanf("%d", &N) != EOF)
        {
            memset(dx, falsesizeof(dx));
            memset(dy, falsesizeof(dy));
            memset(Ly, falsesizeof(Ly));

            for(int i=1; i<=N; i++)
            for(int j=1; j<=N; j++)
            {
                scanf("%d", &w[i][j]);
                dx[i] = max(dx[i], w[i][j]);
            }

            printf("%d ", KM());
        }

        return 0;
    }
    View Code
  • 相关阅读:
    css实现梯形
    CSS3自定义滚动条样式 -webkit-scrollbar
    MySQL-5.6.13免安装版配置方法
    CSS边框长度控制
    The Shapes of CSS(css的形状)
    CSS制作图形速查表
    使用onclick跳转到其他页面/跳转到指定url
    TCP/IP协议
    jQuery实现全选、反选和不选功能
    checkbox在vue中的用法小结
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4706346.html
Copyright © 2011-2022 走看看