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

    题目描述

    学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。

    个男生和个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴。

    Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 

    Cathy还需要考虑两个人一起跳舞是否方便,比如身高体重差别会不会太大,计算得出 ,表示第i个男生和第j个女生一起跳舞时的不协调程度。

    当然,还需要考虑很多其他问题。

    Cathy想先用一个程序通过求出一种方案,再手动对方案进行微调。

    Cathy找到你,希望你帮她写那个程序。

    一个方案中有n对舞伴,假设没对舞伴的喜悦程度分别是,假设每对舞伴的不协调程度分别是。令

    Cathy希望C值最大。

    输入输出格式

    输入格式:

    第一行一个整数n。

    接下来n行,每行n个整数,第i行第j个数表示

    接下来n行,每行n个整数,第i行第j个数表示

    输出格式:

    一行一个数,表示C的最大值。四舍五入保留6位小数,选手输出的小数需要与标准输出相等。

    输入输出样例

    输入样例#1:
    3
    19 17 16
    25 24 23
    35 36 31
    9 5 6
    3 4 2
    7 8 9
    输出样例#1:
    5.357143

    说明

    对于10%的数据,

    对于40%的数据,

    另有20%的数据,

    对于100%的数据,

    思路:二分答案+费用流

    一开始,边的费用没有想到,其实移一下项就好了。

    然后,就见识到了什么叫卡常数,蒟蒻常数巨大。。。

    于是就开始借鉴大佬的优化,发现大佬写的是紫书上的板子,果然,手模代码不靠谱吗?

    丧失OI路的信心。

    事实证明:结构体是极慢的。

     7.3s->4.1s

    代码实现:

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define inf -1e9
     5 using namespace std;
     6 const int maxn=110;
     7 const int maxm=maxn*maxn<<2;
     8 queue<int>q;
     9 int n,s,t,a,b;
    10 double l,r,mid,ans,error=1e-7;
    11 int map[maxn][maxn][2],h[maxn*maxn<<1],hs=1;
    12 int e_q[maxm],e_z[maxm],e_n[maxm],p[maxn<<1];
    13 bool e_w[maxm],v[maxn<<1];
    14 double e_f[maxm],w[maxn<<1];
    15 char r_w[30],r_l;
    16 int read(int &x){
    17     while(r_w[0]=getchar(),r_w[0]<'0'||r_w[0]>'9');r_l=1;
    18     while(r_w[r_l]=getchar(),r_w[r_l]>='0'&&r_w[r_l]<='9') r_l++;
    19     for(int i=0;i<r_l;i++) x=x*10+r_w[i]-'0';
    20 }
    21 inline int min_(int x,int y){return x<y?x:y;}
    22 void add(int x,int y,double z){
    23     ++hs,e_q[hs]=x,e_z[hs]=y,e_n[hs]=h[x],e_w[hs]=true,e_f[hs]=z,h[x]=hs;
    24     ++hs,e_q[hs]=y,e_z[hs]=x,e_n[hs]=h[y],e_w[hs]=false,e_f[hs]=-z,h[y]=hs;
    25 }
    26 void MCMF(){
    27     while(1){
    28         for(int i=0;i<=t;i++) w[i]=inf;
    29         memset(v,0,sizeof(v));
    30         q.push(s),w[s]=false;
    31         while(!q.empty()){
    32             a=q.front(),q.pop(),v[a]=0;
    33             for(int i=h[a];i;i=e_n[i])
    34             if(e_w[i]&&w[e_z[i]]<e_f[i]+w[a]){
    35                 b=e_z[i],p[b]=i;
    36                 w[b]=e_f[i]+w[a];
    37                 if(!v[b]) q.push(b),v[b]=true;
    38             }
    39         }
    40         if(w[t]==inf||(ans<0&&w[t]<0)) return;
    41         else ans+=w[t];
    42         for(int i=t;i!=s;i=e_q[p[i]]) e_w[p[i]]=false,e_w[p[i]^1]=true;
    43     }
    44 }
    45 int main(){
    46     read(n);
    47     s=0,t=n*2+1;
    48     for(int i=1;i<=n;i++)
    49     for(int j=1;j<=n;j++)
    50     read(map[i][j][0]);
    51     for(int i=1;i<=n;i++)
    52     for(int j=1;j<=n;j++)
    53     read(map[i][j][1]);
    54     l=0,r=1e4;
    55     while(r-l>error){
    56         mid=(l+r)/2,ans=0;
    57         memset(h,0,sizeof(h)),hs=1;
    58         for(int i=1;i<=n;i++) add(s,i,0),add(i+n,t,0);
    59         for(int i=1;i<=n;i++)
    60         for(int j=1;j<=n;j++)
    61         add(i,j+n,map[i][j][0]-mid*map[i][j][1]);
    62         MCMF();
    63         if(ans>0) l=mid;
    64         else r=mid;
    65     }
    66     printf("%.6lf",r);
    67     return 0;
    68 }

    傻逼题我都改了这么久,药丸药丸。

  • 相关阅读:
    高可用、高并发浅析
    正则表达式笔记
    linux下通过脚本切换当前工作目录
    nginx学习笔记
    二进制安全
    负载均衡相关
    有用的shell命令
    TCP服务器/客户端代码示例
    UDP服务器/客户端代码示例
    GCC链接的几个注意点
  • 原文地址:https://www.cnblogs.com/J-william/p/6736129.html
Copyright © 2011-2022 走看看