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

    题目大意:

    有n个男生和n个女生跳舞。第i个男生和第j个女生组合会产生a[i][j]的喜悦程度和b[i][j]的不协调值。

    现在你要找到一种方案,使喜悦程度总和与不协调值总和的比值最大。求这个比值。

    解题思路:

    分数规划问题。

    即令(frac{sum a}{sum b})最大。

    令其为C,则(sum a=Csum b)。

    (sum a-Csum b=0)。

    二分C,则若(sum a-Csum bgeq 0),则答案可行。

    判断答案的可行性,发现这是个二分图带权匹配问题,跑最大费用最大流即可,两点之间的费用即为(a[i][j]-C imes b[i][j])。

    若费用大于等于0则可行。

    C++ Code:

    #include<bits/stdc++.h>
    const int S=0,T=202;
    int n,cnt;
    int a[105][105],b[105][105],head[205],fl[205],pre[205],q[40004];
    int from[99999],to[99999],nxt[99999],cap[99999];double cost[99999];
    bool vis[205];
    double dis[205];
    inline int min(int a,int b){return a<b?a:b;}
    void spfa(int&flow,double&C){
        for(dis[S]=0;;){
            for(int i=S+1;i<=T;++i)dis[i]=-1e17;
            memset(vis,0,sizeof vis);
            memset(fl,0x3f,sizeof fl);
            memset(pre,0,sizeof pre);
            vis[S]=1;
            int l=0,r=1;
            for(q[1]=S;l!=r;){
                int u=q[l=l%40000+1];
                vis[u]=false;
                for(int i=head[u];~i;i=nxt[i])
                if(cap[i]&&dis[to[i]]<dis[u]+cost[i]){
                    dis[to[i]]=dis[u]+cost[i];
                    fl[to[i]]=min(fl[u],cap[i]);
                    pre[to[i]]=i;
                    if(!vis[to[i]])
                    vis[q[r=r%40000+1]=to[i]]=1;
                }
            }
            if(dis[T]<-1e16)return;
            flow+=fl[T];
            C+=dis[T]*fl[T];
            for(int i=T;i;i=from[pre[i]]){
                --cap[pre[i]];
                ++cap[pre[i]^1];
            }
        }
    }
    bool check(double k){
        cnt=1;
        for(int i=1;i<=n;++i){
            cap[++cnt]=1;
            cap[++cnt]=0;
            cap[++cnt]=1;
            cap[++cnt]=0;
            for(int j=1;j<=n;++j){
                cap[++cnt]=1;
                cost[cnt]=a[i][j]-k*b[i][j];
                cap[++cnt]=0;
                cost[cnt]=-cost[cnt-1];
            }
        }
        int flow=0;double C=0;
        spfa(flow,C);
        return C+1e-8>=0;
    }
    int main(){
        memset(head,-1,sizeof head);
        scanf("%d",&n);
        cnt=1;
        for(int i=1;i<=n;++i){
            from[++cnt]=S;to[cnt]=i;nxt[cnt]=head[S];head[S]=cnt;cost[cnt]=0;
            from[++cnt]=i;to[cnt]=S;nxt[cnt]=head[i];head[i]=cnt;cost[cnt]=0;
            from[++cnt]=i+n;to[cnt]=T;nxt[cnt]=head[i+n];head[i+n]=cnt;cost[cnt]=0;
            from[++cnt]=T;to[cnt]=i+n;nxt[cnt]=head[T];head[T]=cnt;cost[cnt]=0;
            for(int j=1;j<=n;++j){
                from[++cnt]=i;to[cnt]=j+n;nxt[cnt]=head[i];head[i]=cnt;
                from[++cnt]=j+n;to[cnt]=i;nxt[cnt]=head[j+n];head[j+n]=cnt;
            }
        }
        for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)scanf("%d",&a[i][j]);
        for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)scanf("%d",&b[i][j]);
        double l=0,r=1e6,ans=0;
        while(l+1e-8<r){
            double mid=(l+r)/2;
            if(check(mid))l=mid+1e-8,ans=mid;
            else r=mid-1e-8;
        }
        printf("%.6f
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    requests.session()发送请求 和使用requests直接发送请求的区别
    axios请求接口如何将data转换formdata?
    yaml简单使用
    Appium-send_keys 无法写入?
    Appium-滑动操作
    Appium -appium desktop工具使用
    Appium学习笔记(2)adb常用命令
    Appium学习笔记(1)appium配置-起步
    Django学习笔记(20)celery_tasks 异步任务初识
    Django学习笔记(19)HttpResponse/JsonResponse /render /redirect/Http404
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9605153.html
Copyright © 2011-2022 走看看