• BZOJ-4819: 新生舞会(01分数规划+费用流)


    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

    思路:显然的01分数规划型二分,二分C,然后判断最大费用最大流,如果最大费用大于0,说明当前的C还可以优化。

    (果然zkw费用流跑二分图有点慢。。。

    #include<bits/stdc++.h>
    const double infdis=99999999;
    const int maxn=210;
    using namespace std;
    int a[maxn][maxn],b[maxn][maxn];
    int To[maxn*maxn],Laxt[maxn],Next[maxn*maxn],cap[maxn*maxn];
    int S,T,N,cnt; double dis[maxn],cost[maxn*maxn];
    bool inq[maxn],vis[maxn];
    deque<int>q;
    void add(int u,int v,int c,double cc)
    { 
        Next[++cnt]=Laxt[u];Laxt[u]=cnt;
        To[cnt]=v;cap[cnt]=c;cost[cnt]=cc; 
    }
    bool spfa()
    {
        for(int i=0;i<=T;i++) inq[i]=0;
        for(int i=0;i<=T;i++) dis[i]=infdis; //这样更新,必须保证T的编号最大 
        inq[T]=1; dis[T]=0; q.push_back(T);
        while(!q.empty())
        {    
            int u=q.front(); q.pop_front();
            inq[u]=0;
            for(int i=Laxt[u];i;i=Next[i])
            {
                int v=To[i];
                if(cap[i^1]&&dis[v]>dis[u]-cost[i])
                {
                    dis[v]=dis[u]-cost[i];
                    if(!inq[u]){
                        inq[v]=1;
                        if(q.empty()||dis[v]>dis[q.front()]) q.push_back(v);
                        else q.push_front(v);
                    }
                }
            }
        }
        return dis[S]<infdis;
    }
    int dfs(int u,int flow)
    {
        vis[u]=1;
        if(u==T||flow==0) return flow;
        int tmp,delta=0;
        for(int i=Laxt[u];i;i=Next[i])
        {
            int v=To[i];
            if((!vis[v])&&cap[i]&&dis[v]==dis[u]-cost[i])
            {
                tmp=dfs(v,min(cap[i],flow-delta));
                delta+=tmp; cap[i]-=tmp; cap[i^1]+=tmp;
            }
        }
        return delta;
    }
    bool check(double Mid)
    {
        int i,j; double res=0; cnt=1; S=0; T=N+N+1;
        for(i=0;i<=T;i++) Laxt[i]=0;
        for(i=1;i<=N;i++) {
            add(S,i,1,0); add(i,S,0,0);
            add(i+N,T,1,0); add(T,i+N,0,0);
            for(j=1;j<=N;j++) 
              add(i,N+j,1,Mid*b[i][j]-a[i][j]),add(N+j,i,0,1.0*a[i][j]-Mid*b[i][j]);
        }
        while(spfa()){
            vis[T]=1;
            while(vis[T]){
                for(i=0;i<=T;i++) vis[i]=0;
                res+=dis[S]*dfs(S,N);
            }
        }
        return res<0;
    }
    int main()
    {
        scanf("%d",&N);
        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.0,R=10000.0,Mid,ans=0;
        while(L+1e-8<=R){
            Mid=(L+R)/2.0;
            if(check(Mid)) L=Mid;
            else ans=Mid,R=Mid;
        }
        printf("%.6lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    python-条件判断
    获取网卡名称
    vSphere Client安装
    python远程执行命令
    xorm操作
    httpd服务安装配置
    error: failed to push some refs to 'git@gitee.com:xxxx'
    三种获取数据的方法fetch和ajax和axios
    react组件的生命周期
    react在移动端的自适应布局
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9397800.html
Copyright © 2020-2023  润新知