zoukankan      html  css  js  c++  java
  • 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]求出一种方案,再手动对方案进行微调。Cathy找到你,希望你帮她写那个程序。一个方案中有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$分数规划+费用流。

    好吧其实这题正解好像是$KM$算法,不过忘记写了。。

    这是一道经典的$01$分数规划的问题,要解决这类问题,我们首先考虑二分答案。

    如果$frac{sum_{i=1}^{n}a^{'}i}{sum_{i=1}^{n}b^{'}i}>mid$

    即$sum_{i=1}^{n}a^{'}i>midsum_{i=1}^{n}b^{'}i$

    $sum_{i=1}^{n}a^{'}i-mid*b^{'}i>0$,那么$ans$就会更大。

    所以我们每次跑费用流的费用就是$a[i][j]-mid*b[i][j]$,我们要求出这个图的最大费用最大流,那么我们把费用取反就行了。

    然后我们判断这个费用是否可行,再二分就行了。实数二分,$eps$大概取$10^{-7}$吧。。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define inf (1e18)
    15 #define eps (1e-7)
    16 #define N (510)
    17 #define il inline
    18 #define RG register
    19 #define ll long long
    20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    21 
    22 using namespace std;
    23 
    24 struct edge{
    25     int nt,to,flow,cap;
    26     double dis;
    27 }g[200010];
    28 
    29 int head[N],f[N],vis[N],fa[N],p[N],a[N][N],b[N][N],q[1000010],S,T,n,num,flow;
    30 double dis[N],cost,ans;
    31 
    32 il int gi(){
    33     RG int x=0,q=1; RG char ch=getchar();
    34     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    35     if (ch=='-') q=-1,ch=getchar();
    36     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    37     return q*x;
    38 }
    39 
    40 il void insert(RG int from,RG int to,RG int cap,RG double cost){
    41     g[++num]=(edge){head[from],to,0,cap,cost},head[from]=num; return;
    42 }
    43 
    44 il int bfs(RG int S,RG int T){
    45     for (RG int i=1;i<=T;++i) dis[i]=inf;
    46     RG int h=0,t=1; q[t]=S,dis[S]=0,f[S]=1<<30,vis[S]=1;
    47     while (h<t){
    48     RG int x=q[++h],v;
    49     for (RG int i=head[x];i;i=g[i].nt){
    50         v=g[i].to;
    51         if (dis[v]>dis[x]+g[i].dis && g[i].cap>g[i].flow){
    52         dis[v]=dis[x]+g[i].dis,fa[v]=x,p[v]=i;
    53         f[v]=min(f[x],g[i].cap-g[i].flow);
    54         if (!vis[v]) vis[v]=1,q[++t]=v;
    55         }
    56     }
    57     vis[x]=0;
    58     }
    59     if (fabs(dis[T]-inf)<eps) return 0;
    60     flow+=f[T],cost+=f[T]*dis[T];
    61     for (RG int i=T;i!=S;i=fa[i])
    62     g[p[i]].flow+=f[T],g[p[i]^1].flow-=f[T];
    63     return 1;
    64 }
    65 
    66 il int check(RG double key){
    67     RG double res; memset(head,0,sizeof(head)),num=1;
    68     for (RG int i=1;i<=n;++i){
    69     insert(S,i,1,0),insert(i,S,0,0);
    70     insert(n+i,T,1,0),insert(T,n+i,0,0);
    71     }
    72     for (RG int i=1;i<=n;++i)
    73     for (RG int j=1;j<=n;++j){
    74         res=a[i][j]-key*b[i][j];
    75         insert(i,n+j,1,-res),insert(n+j,i,0,res);
    76     }
    77     flow=cost=0; while (bfs(S,T)); return cost<eps;
    78 }
    79 
    80 il void work(){
    81     n=gi(),S=2*n+1,T=2*n+2;
    82     for (RG int i=1;i<=n;++i)
    83     for (RG int j=1;j<=n;++j) a[i][j]=gi();
    84     for (RG int i=1;i<=n;++i)
    85     for (RG int j=1;j<=n;++j) b[i][j]=gi();
    86     RG double l=0.0,r=100000.0,mid;
    87     while (fabs(r-l)>eps){
    88     mid=(l+r)/2;
    89     if (check(mid)) ans=mid,l=mid; else r=mid;
    90     }
    91     printf("%0.6lf",ans); return;
    92 }
    93 
    94 int main(){
    95     File("ball");
    96     work();
    97     return 0;
    98 }
  • 相关阅读:
    C#编写ActiveX在WEB中应用
    Asp.net中Array的用法
    CAB打包方法
    C#获取文件路径的几种方法
    使用MakeCAB.exe命令创建CAB文件
    VS2005 工具里添加“OLE/COM 对象查看器”命令
    【转载】ASP.NET MVC中Controller与View之间的数据传递总结
    F如何配置外向交货单的定价过程
    解决 局域网XP无权限访问的问题 (转)
    U盘装XP系统(含截图,2012最新原创超简单方法)
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6700301.html
Copyright © 2011-2022 走看看