• BZOJ 4819 SDOI2017 新生舞会


    4819: [Sdoi2017]新生舞会

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1239  Solved: 642
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

     
    二分+费用流
    首先二分答案mid  那么原问题的判断就变成了 a1+a2+a3+....+an>=mid*(b1+b2+b3+....+bn)
    建图的话 i向j连一条ai-bj的边即可  最后跑费用流看一下最大费用是否大于等于0即可
    /**************************************************************
        Problem: 4819
        User: zhangenming
        Language: C++
        Result: Accepted
        Time:5648 ms
        Memory:5296 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define ll long long
    #define eps 1e-7
    #define inf 1e9+10
    using namespace std;
    inline int read(){
        int x=0;int f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=1e5+10;
    inline void print(double t){
        printf("%.6lf
    ",t);
    }
    struct node{
        int y,next,f,back;
        double w;
    }e[MAXN];
    int linkk[MAXN],len,n,m,a[110][110],b[110][110],vis[MAXN],s,t;
    double dis[MAXN],ans;
    inline void insert(int x,int y,int f,double w){
        e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].back=len+1;e[len].f=f;e[len].w=w;
        e[++len].y=x;e[len].next=linkk[y];linkk[y]=len;e[len].back=len-1;e[len].f=0;e[len].w=-w;
    }
    inline bool spfa(){
        deque<int> q;q.push_back(t);
        for(int i=s;i<=t;i++) vis[i]=0,dis[i]=-inf;
        vis[t]=1;dis[t]=0;
        while(!q.empty()){
            int tn=q.front();q.pop_front();
            for(int i=linkk[tn];i;i=e[i].next){
                if(e[e[i].back].f&&dis[e[i].y]<dis[tn]-e[i].w){
                    dis[e[i].y]=dis[tn]-e[i].w;
                    if(!vis[e[i].y]){
                        if(!q.empty()&&dis[e[i].y]>dis[q.front()]) q.push_front(e[i].y);
                        else q.push_back(e[i].y);
                        vis[e[i].y]=1;
                    }
                }
            }
            vis[tn]=0;
        }
        //printf("%.6lf
    ",dis[s]);
        return dis[s]!=-inf;
    }
    inline int getcost(int x,int flow){
        vis[x]=1;int f=0,d;
        if(x==t) return flow;
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].f&&dis[e[i].y]==dis[x]-e[i].w&&!vis[e[i].y]){
                if(d=getcost(e[i].y,min(flow-f,e[i].f))){
                    f+=d;e[i].f-=d;e[e[i].back].f+=d;
                    //cout<<d<<' ';print(e[i].w);
                    ans+=1.0*d*e[i].w;if(f==flow) return flow;
                }
            }
        }
        return f;
    }
    inline void zkw(){
        while(spfa()){
            vis[t]=1;
            while(vis[t]){
                for(int i=s;i<=t;i++) vis[i]=0;
                getcost(s,inf);
            }
        }
    }
    inline bool solve(double mid){
        //print(mid);
        for(int i=s;i<=t;i++) linkk[i]=0;
        len=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                insert(i,j+n,1,a[i][j]-1.0*mid*b[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            insert(s,i,1,0);insert(i+n,t,1,0);
        }
        ans=0;zkw();
        if(ans>0) return true;
        else return false;
    }
    int main(){
        //freopen("All.in","r",stdin);
        //freopen("zh.out","w",stdout);
        n=read();s=0;t=n*n+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                a[i][j]=read();
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                b[i][j]=read();
            }
        }
        double l=0;double r=10010;
        double ans1=0;
        while(abs(r-l)>=eps){
            double mid=(l+r)*0.5;
            if(solve(mid)) ans1=max(ans1,mid),l=mid;
            else r=mid;
        }
        printf("%.6lf
    ",r);
        return 0;
    }
    

      

  • 相关阅读:
    #3146. 「APIO 2019」路灯
    #3145. 「APIO 2019」桥梁
    #3144. 「APIO 2019」奇怪装置
    雅礼集训2019 D7T2 Subsequence
    Luogu P3600 随机数生成器
    CF 704 D. Captain America
    Luogu P2570 [ZJOI2010]贪吃的老鼠
    Loj #2585. 「APIO2018」新家
    Access denied for user 'root'@'localhost' (using password: NO)
    MySql修改密码
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/9485095.html
Copyright © 2020-2023  润新知