zoukankan      html  css  js  c++  java
  • [BZOJ4819]新生舞会

    [BZOJ4819][Sdoi2017]新生舞会

    Description

    学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴。Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度。Cathy还需要考虑两个人一起跳舞是否方便,比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度。当然,还需要考虑很多其他问题。Cathy想先用一个程序通过a[i][j]和b[i][j]。
    求出一种方案,再手动对方案进行微调。C athy找到你,希望你帮她写那个程序。一个方案中有n对舞伴,假设没对舞伴的喜悦程度分别是a'1,a'2,...,a'n,假设每对舞伴的不协调程度分别是b'1,b'2,...,b'n。令C=(a'1+a'2+...+a'n)/(b'1+b'2+...+b'n),Cathy希望C值最大。

    Input

    第一行一个整数n。接下来n行,每行n个整数,第i行第j个数表示a[i][j]。接下来n行,每行n个整数,第i行第j个数表示b[i][j]。1<=n<=100,1<=a[i][j],b[i][j]<=10^4

    Output

    一行一个数,表示C的最大值。四舍五入保留6位小数,选手输出的小数需要与标准输出相等

    Sample Input

    3
    19 17 16
    25 24 23
    35 36 31
    9 5 6
    3 4 2
    7 8 9

    Sample Output

    5.357143

    试题分析

    题面是Smg?
    分数规划通常是解决一类平均值极值问题的方法,设(F(x),G(x))为线性函数,求({ans=frac{F(x)}{G(x)} })
    其中F,G各项的系数(in [0,1])。 考虑将问题转化为二分,就是求是否存在(frac{F(x)}{G(x)} ge ans),移项得到(F(x)-ans imes G(x)ge 0)
    二分找到(leq 0)的点即可。
    对于这道题来说就非常裸了,就是一个带负权的二分图匹配,费用流水过。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
     
    inline int read(){
        int x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int INF = 1047483600;
    const int MAXN = 300010;
     
    int cos_a[101][101],cos_b[101][101];
    int N; int Root[300001],Node[MAXN+1],C[MAXN+1];
    double Cost[MAXN+1]; int Next[MAXN+1],cnt;
    bool inq[MAXN+1]; double dis[MAXN+1];
    int T,S;
     
    inline bool BFS(){
        deque<int> que; memset(inq,false,sizeof(inq));
        for(int i=0;i<=T;i++) dis[i]=INF; dis[T]=0; que.push_back(T); inq[T]=true;
        while(!que.empty()){
            int k=que.front(); que.pop_front(); inq[k]=false;
            for(int x=Root[k];x!=-1;x=Next[x]){
                int v=Node[x];
                if(C[x^1]>0&&dis[v]>dis[k]-Cost[x]){
                    dis[v]=dis[k]-Cost[x];
                    if(!inq[v]){
                        if(que.empty()||dis[que.front()]>=dis[v]) que.push_front(v);
                        else que.push_back(v);
                        inq[v]=true;
                    }
                }
            } 
        }
        return dis[S]<INF;
    }
    double ret=0;
    inline int DFS(int k,int t){
        if(k==T) {inq[k]=true; return t;} inq[k]=true;
        int res=0;
        for(int x=Root[k];x!=-1;x=Next[x]){
            int v=Node[x];
            if(C[x]>0&&dis[v]==dis[k]-Cost[x]&&!inq[v]){
                int tmp=DFS(v,min(t,C[x]));
                ret+=1.0*Cost[x]*tmp; C[x]-=tmp; C[x^1]+=tmp;
                res+=tmp; t-=tmp; if(!t) return res;
            }
        } return res;
    }
    inline void insert(int u,int v,int c,double w){
        Node[cnt]=v; Next[cnt]=Root[u]; Cost[cnt]=w; C[cnt]=c; Root[u]=cnt++; return ;
    }
    inline bool check(double k){
        memset(Root,-1,sizeof(Root)); cnt=0; ret=0;
        S=0; T=2*N+1;
        for(int i=1;i<=N;i++) {
            insert(S,i,1,0); insert(i,S,0,0);
            insert(i+N,T,1,0); insert(T,i+N,0,0);
        }
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++){
                insert(i,j+N,1,k*cos_b[i][j]-cos_a[i][j]);
                insert(j+N,i,0,cos_a[i][j]-k*cos_b[i][j]);
            }
        } while(BFS()) DFS(S,INF);
        return ret<=(1e-7);
    }
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read();
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++) cos_a[i][j]=read();
        } for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++) cos_b[i][j]=read();
        } double l=0.0,r=1e6,ans=0;
        while(r-l>=1e-7){
            double mid=(l+r)/2.0;
            if(check(mid)) ans=mid,l=mid;
            else r=mid; 
        } printf("%.6lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    忍道
    2020.12.27
    2020.12.26
    2020.12.25
    记录
    卸载抖音
    汉化报告修改配置文件
    tcp校验client客户端的合法性
    tcp连接发送命令客户端接收后返回结果给服务端
    logging模块
  • 原文地址:https://www.cnblogs.com/wxjor/p/9461168.html
Copyright © 2011-2022 走看看