• T66597 小xzy的任务 题解


    T66597 小xzy的任务

    题目背景

    今天,小xzy的班主任交给他一个严肃的任务,匹配羽毛球运动员! ! !

    题目描述

    羽毛球队有男女运动员各n人。给定2n×n矩阵PQPij是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势;Qij是女运动员ii和男运动员j配合的女运动员竞赛优势。由于技术配合和心理状态等各种因素影响,Pij不一定等于Qji。男运动员ii和女运动员jj配对组成混合双打的男女双方竞赛优势为PijQji。设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。

    编程任务

    设计一个算法,对于给定的男女运动员竞赛优势,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。

    输入输出格式

    输入格式:

    第一行有1 个正整数n (2n1000)。接下来的2n行,每行n个数。前n行是p,后n行是q。

    输出格式:

    一个整数,计算出的男女双方竞赛优势的总和的最大值。

    输入输出样例

    输入样例#1: 
    3
    10 2 3
    2 3 4
    3 4 5
    2 2 2
    3 5 3
    4 5 1
    
    输出样例#1: 
    52
    

    说明

    0n1000,0Pij,Qij1000

    第一个测试点:n100

    这题我们把男运动员和女运动员看成两个集合,于是这题便可以看成是带权二分图匹配。

    带权二分图匹配通常使用KM算法。

    不了解KM算法的请移步。

    code:

    #include <cstdio>
    const int MAXN=2005;
    const int INF=0x3f3f3f3f;
    int n,now=0;
    int rela[MAXN][MAXN],match[MAXN];
    int ex_boy[MAXN],ex_girl[MAXN],slack[MAXN];
    int vis_boy[MAXN],vis_girl[MAXN];
    int boy[MAXN][MAXN],girl[MAXN][MAXN];
    
    void read(int &x)
    {
    	int out=1;
    	char c;x=0;
    	while(c<'0' || c>'9'){if(c=='-')out=-1;c=getchar();}
    	while(c>='0'&&c<='9')
    	{
    		x=x*10+c-48;
    		c=getchar();
    	}
    	x=x*out;
    }
    
    void write(long long x)
    {
    	if(x>10)write(x/10);
    	putchar(x%10+48);
    }
    
    void init()
    {
        read(n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)read(boy[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)read(girl[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                rela[i][j]=boy[i][j]*girl[j][i];
    }
    
    int dfs(int x)
    {
        int cp;
        vis_girl[x]=now;
        for(int y=1;y<=n;y++)
        {
            if(vis_boy[y]==now)continue;
            cp=ex_girl[x]+ex_boy[y]-rela[x][y];
            if(cp==0)
            {
                vis_boy[y]=now;
                if((match[y]==0)||dfs(match[y]))
                {
                    match[y]=x;return true;
                }
            }
            else if(cp<slack[y])slack[y]=cp;
        }
        return false;
    }
    
    long long KM()
    {
        for(int i=1;i<=n;i++)
        {
            match[i]=ex_girl[i]=ex_boy[i]=0;
            for(int j=1;j<=n;j++)
                if(rela[i][j]>ex_girl[i])ex_girl[i]=rela[i][j];
        } 
        for(int i=1;i<=n;i++)
        {
    		now=0;
    		for(int j=1;j<=n;j++)
    		{
    			slack[j]=INF;
    			vis_boy[j]=vis_girl[j]=0;
    		}
            while(1)
            {
                now++;
                if(dfs(i))break;
                int d=INF;
                for(int j=1;j<=n;j++)if(vis_boy[j]!=now&&slack[j]<d)d=slack[j];
                for(int j=1;j<=n;j++)
                {
                    if(vis_girl[j]==now)ex_girl[j]-=d;
                    if(vis_boy[j]==now)ex_boy[j]+=d;
                    else slack[j]-=d;
                }
            }
        }
        long long res=0;
        for(int i=1;i<=n;i++)res+=rela[match[i]][i];
        return res;
    }
    
    int main()
    {
        init();
        write(KM());
        return 0;
    }
    

      

  • 相关阅读:
    准备重启blog。。。
    愿我成功省一。
    [LUOGU]P5502 [JSOI2015]最大公约数
    [LUOGU]P3400 仓鼠窝
    [LUOGU]P5149 会议座位
    OI退役记
    新开博客园~~
    1108 模拟赛
    牛客1102
    题解 CF21B 【Intersection】
  • 原文地址:https://www.cnblogs.com/lzxzy-blog/p/xinzhaoyang.html
Copyright © 2020-2023  润新知