题目分享J 二代目

Posted lin4xu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题目分享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;
}

 

以上是关于题目分享J 二代目的主要内容,如果未能解决你的问题,请参考以下文章

题目分享B 三代目

题目分享C 二代目

题目分享L 二代目

题目分享L 二代目

题目分享F 二代目

题目分享H 二代目