码迷,mamicode.com
首页 > 其他好文 > 详细

[SDOI2017]新生舞会 题解

时间:2020-03-21 09:17:46      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:idt   ace   sdi   bit   inf   span   com   using   www   

 

首先是题目链接:

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]新生舞会 题解

标签:idt   ace   sdi   bit   inf   span   com   using   www   

原文地址:https://www.cnblogs.com/megatrio/p/12536432.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!