[SDOI2017]新生舞会 题解

Posted megatrio

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SDOI2017]新生舞会 题解相关的知识,希望对你有一定的参考价值。

 

首先是题目链接:

luogu:https://www.luogu.com.cn/problem/P3705

loj:https://loj.ac/problem/2003

bzoj:http://www.lydsy.com/JudgeOnline/problem.php?id=4819


发现题目要求 技术图片最大化

稍作变形得 技术图片

于是容易想到二分答案技术图片,并将第技术图片个男生和第技术图片个女生连一条权值为技术图片的边,用KM算法进行带权二分图最大匹配。

如果匹配结果大于等于技术图片,则答案小于等于技术图片

代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define N 110
#define INF 1000000007
inline int read()
{
    bool f=0;int x=0;char ch;
    do{ch=getchar();f|=(ch==-);}while(!isdigit(ch));
    do{x=(x<<1)+(x<<3)+ch-0;ch=getchar();}while(isdigit(ch));
    return f?-x:x;
}
using namespace std;
int n,a[N][N],b[N][N],match[N];
double lx[N],ly[N],val[N][N];
bool vx[N],vy[N];
bool dfs(int x)
{
    vx[x]=1;
    rep(y,1,n)
        if(!vy[y]&&lx[x]+ly[y]-val[x][y]==0)
        {
            vy[y]=1;
            if(match[y]==-1||dfs(match[y]))
            {
                match[y]=x;
                return 1;
            }
        }
    return 0;
}
inline bool KM()
{
    memset(ly,0.0,sizeof(ly));
    rep(i,1,n)
    {
        lx[i]=-INF;
        rep(j,1,n)lx[i]=max(lx[i],val[i][j]);
    }
    memset(match,-1,sizeof(match));
    rep(i,1,n)
        while(1)
        {
            memset(vx,0,sizeof(vx));
            memset(vy,0,sizeof(vy));
            if(dfs(i)) break;
            double d=INF;
            rep(x,1,n)if(vx[x])
                rep(y,1,n)if(!vy[y])
                    d=min(d,lx[x]+ly[y]-val[x][y]);
            if(d==INF) return -1;
            rep(x,1,n) if(vx[x])
                lx[x]-=d;
            rep(y,1,n) if(vy[y])
                ly[y]+=d;
        }
    double res=0;
    rep(i,1,n) if(match[i]>-1)
        res+=val[match[i]][i];
    return res>0;
}
int main()
{
    n=read();
    rep(i,1,n)rep(j,1,n) a[i][j]=read();
    rep(i,1,n)rep(j,1,n) b[i][j]=read();
    double l=0,r=1e4,mid;
    while(r-l>=1e-8)
    {
        mid=l+(r-l)/2;
        rep(i,1,n)rep(j,1,n)val[i][j]=1.0*a[i][j]-mid*b[i][j];
        if(KM()) l=mid;
        else r=mid;
    }
    printf("%.6lf",mid);
    return 0;
}

 


以上是关于[SDOI2017]新生舞会 题解的主要内容,如果未能解决你的问题,请参考以下文章

[Sdoi2017]新生舞会

[Sdoi2017]新生舞会

SDOI2017 新生舞会

[BZOJ4819][SDOI2017]新生舞会

[SDOI2017]新生舞会

[BZOJ]4819: [Sdoi2017]新生舞会