zoukankan      html  css  js  c++  java
  • bzoj 4819 [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
     
    题解:
    这题卡精度卡常卡到死哈.
    建图很好想哈,i-j 容量为1 费用为a[i][j]-b[i][j]*mid   然后二分mid即可
    注意邻接表不要开结构体,常数大的只能过50了
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int N=203,inf=2e8,M=40505;
     8 const double eps=1e-8;
     9 double mapone[105][105],maptwo[105][105];
    10 int n,head[N],num=0;
    11 int net[M],to[M],dis[M];double cost[M];
    12 void init(int x,int y,int dist,double costs){
    13     net[++num]=head[x];to[num]=y;dis[num]=dist;cost[num]=costs;head[x]=num;
    14 }
    15 void addedge(int x,int y,int dis,double cost){
    16     init(x,y,dis,cost);init(y,x,0,-cost);
    17 }
    18 int S=0,T,q[N*10],mod=N*10,pre[N];double f[N];bool vis[N];double st=0;
    19 void updata(){
    20     int now=T,t;
    21     while(now){
    22         t=pre[now];
    23         dis[t]--;dis[t^1]++;
    24         now=to[t^1];
    25     }
    26     st+=f[T];
    27 }
    28 bool maxflow(){
    29     int x,u,t=0,sum=1;
    30     for(int i=S;i<=T;i++)vis[i]=false,f[i]=-inf;
    31     vis[S]=true;f[S]=0;q[1]=S;
    32     while(t!=sum){
    33         t++;if(t==mod)t=0;x=q[t];
    34         for(int i=head[x];i;i=net[i]){
    35             u=to[i];
    36             if(dis[i]<=0)continue;
    37             if(f[x]+cost[i]>f[u]){
    38                 f[u]=f[x]+cost[i];pre[u]=i;
    39                 if(!vis[u]){
    40                     vis[u]=true;
    41                     sum++;if(sum==mod)sum=0;q[sum]=u;
    42                 }
    43             }
    44         }
    45         vis[x]=false;
    46     }
    47     if(f[T]==-inf || (st<eps && f[T]<eps))return false;
    48     return true;
    49 }
    50 void Clear(){
    51     num=1;st=0;
    52     memset(head,0,sizeof(head));
    53 }
    54 bool check(double lim)
    55 {
    56     Clear();
    57     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    58     addedge(i,j+n,1,mapone[i][j]-maptwo[i][j]*lim);
    59     for(int i=1;i<=n;i++)addedge(S,i,1,0),addedge(i+n,T,1,0);
    60     while(maxflow())updata();
    61     return st>=eps;
    62 }
    63 void work()
    64 {
    65     scanf("%d",&n);T=n*2+1;
    66     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    67     scanf("%lf",&mapone[i][j]);
    68     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    69     scanf("%lf",&maptwo[i][j]);
    70     double l=0,mid,ans,r=1e4;
    71     while(l<=r-eps){
    72         mid=(l+r)/2;
    73         if(check(mid))ans=mid,l=mid+eps;
    74         else r=mid-eps;
    75     }
    76     printf("%.6lf
    ",ans);
    77 }
    78 int main()
    79 {
    80     work();
    81     return 0;
    82 }
  • 相关阅读:
    CF1175B Catch Overflow!
    震惊!一蒟蒻竟然写出fhqTreap
    树上差分
    洛谷 P3128 最大流Max Flow
    线段树的标记永久化/二维线段树模板
    矩阵加速~desire drive
    置换相关
    树形图们
    严格单调递增与非严格之间的转换
    记录延续性的一类dp
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7225855.html
Copyright © 2011-2022 走看看