• 题目分享J 二代目


    题意:给一个n行n列的矩阵,构造两个数组a,b,使得对于任意x,y≤n满足mapp[x][y]≤a[x]+b[y]

    分析:这不就是个KM算法的板子题吗?

     (摘自老姚博客)

    所以只需要输出A数组B数组与ans即可(真没啥好说的,我称之为KM算法附赠品)

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int maxn=1e3+1;
    const int maxm=1e6+1;
    const int inf=0x3f3f3f3f;
    
    struct edge
    {
        int to,next;
    }e[maxm];
    int head[maxn];
    int g[maxn][maxn];
    int wx[maxn];
    int wy[maxn];
    int match[maxn];
    bool visx[maxn];
    bool visy[maxn];
    int slack[maxn];
    int cnt,n;
    
    void add(int x,int y)
    {
        e[++cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt;
    }
    
    int dfs(int x)
    {
        visx[x]=1;   
        for(int i=1;i<=n;i++)
        {
            if(!visy[i])
            {    
                int now=wx[x]+wy[i]-g[x][i];
                if(!now)
                { 
                    visy[i]=1;
                    if(!match[i]||dfs(match[i]))
                    {                    
                        match[i]=x;
                        return 1;
                    }
                }
                else slack[i]=min(slack[i],now);
            }
        }
        return 0;
    }
    
    int km()
    {
        memset(match,0,sizeof(match));
        memset(wy,0,sizeof(wy));
        for(int i=1;i<=n;i++)
        {
            memset(slack,0x3f,sizeof(slack));
            while(1)
            {
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(dfs(i)) break;
                int minz=inf;
                for(int j=1;j<=n;j++) if(!visy[j]) minz=min(minz,slack[j]);
                for(int j=1;j<=n;j++) if(visx[j]) wx[j]-=minz;
                for(int j=1;j<=n;j++) if(visy[j]) wy[j]+=minz; else slack[j]-=minz;
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            printf("%d",wx[i]);
            if(i!=n) printf(" ");
            ans+=wx[i];
        }
        printf("
    ");
        for(int i=1;i<=n;i++)
        {    
            printf("%d",wy[i]);
            if(i!=n) printf(" ");
            ans+=wy[i];
        }
        printf("
    ");
        return ans;
    }
    
    int main()
    {
        int m,x,y,z;
        while(scanf("%d",&n)!=EOF)
        {
            memset(wx,0,sizeof(wx));
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    scanf("%d",&g[i][j]);
                    wx[i]=max(wx[i],g[i][j]);
                }
            }
            printf("%d
    ",km());
        }
        return 0;
    }
  • 相关阅读:
    215. Kth Largest Element in an Array (have better solution )
    414. Third Maximum Number
    442. Find All Duplicates in an Array
    448. Find All Numbers Disappeared in an Array
    485. Max Consecutive Ones
    532. K-diff Pairs in an Array
    8. String to Integer (atoi)
    7. Reverse Integer
    [CTSC2012]熟悉的文章(广义后缀自动机+二分答案+单调队列优化DP)
    BZOJ 2119 股市的预测(后缀数组)
  • 原文地址:https://www.cnblogs.com/lin4xu/p/12866325.html
Copyright © 2020-2023  润新知