zoukankan      html  css  js  c++  java
  • [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
    二分答案mid
    然后把每个匹配权值变成a[i][j]-mid*b[i][j](最优比例生成树的套路)
    然后求出最大权值匹配
    没有用KM算法,直接建网络流模型,权值取负,跑最小费用流
    看最小费用是否小于0
    此题卡常,不用结构体快1倍
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<queue>
      7 using namespace std;
      8 int from[200001],next[200001],to[200001],cap[200001];
      9 double dis[200001];
     10 int num=1,head[501],path[501],n;
     11 double dist[501],a[101][101],b[101][101];
     12 bool vis[501];
     13 void add(int u,int v,int c,double d)
     14 {
     15   num++;
     16   next[num]=head[u];
     17   head[u]=num;
     18   to[num]=v;
     19   from[num]=u;
     20   cap[num]=c;
     21   dis[num]=d;
     22 }
     23 bool SPFA(int S,int T)
     24 {int i;
     25   queue<int>Q;
     26   memset(vis,0,sizeof(vis));
     27   memset(path,-1,sizeof(path));
     28   for (i=S;i<=T;i++)
     29     dist[i]=1e9;
     30   Q.push(S);
     31   dist[S]=0;
     32   while (Q.empty()==0)
     33     {
     34       int u=Q.front();
     35       Q.pop();
     36       vis[u]=0;
     37       for (i=head[u];i!=-1;i=next[i])
     38     if (cap[i])
     39       {
     40         int v=to[i];
     41         if (dist[v]>dist[u]+dis[i])
     42           {
     43         dist[v]=dist[u]+dis[i];
     44         path[v]=i;
     45         if (vis[v]==0)
     46           {
     47             vis[v]=1;
     48             Q.push(v);
     49           }
     50           }
     51       }
     52     }
     53   if (dist[T]==1e9) return 0;
     54   return 1;
     55 }
     56 double mincost(int S,int T)
     57 {int i;
     58   double ans=0;
     59   while (SPFA(S,T))
     60     {
     61       for (i=path[T];i!=-1;i=path[from[i]])
     62     {
     63       cap[i]-=1;
     64       cap[i^1]+=1;
     65     }
     66       ans+=dist[T];
     67     }
     68   return ans;
     69 }
     70 bool check(double mid)
     71 {int S,T,i,j;
     72   double ans;
     73   memset(head,-1,sizeof(head));
     74   num=1;S=0;T=2*n+1;
     75   for (i=1;i<=n;i++)
     76     {
     77       add(S,i,1,0);add(i,S,0,0);
     78       add(n+i,T,1,0);add(T,n+i,0,0);
     79     }
     80   for (i=1;i<=n;i++)
     81     {
     82       for (j=1;j<=n;j++)
     83     {
     84       double res=a[i][j]-mid*b[i][j];
     85       add(i,n+j,1,-res);add(n+j,i,0,res);
     86     }
     87     }
     88   ans=mincost(S,T);
     89   if (ans<0) return 1;
     90   return 0;
     91 }
     92 int main()
     93 {int i,j;
     94   cin>>n;
     95   for (i=1;i<=n;i++)
     96     {
     97       for (j=1;j<=n;j++)
     98     {
     99       scanf("%lf",&a[i][j]);
    100     }
    101     }
    102   for (i=1;i<=n;i++)
    103     {
    104       for (j=1;j<=n;j++)
    105     {
    106       scanf("%lf",&b[i][j]);
    107     }
    108     }
    109   double l=0,r=1000000;
    110   while (r-l>1e-7)
    111     {
    112       double mid=(l+r)/2.0;
    113       if (check(mid)) l=mid;
    114       else r=mid;
    115     }
    116   printf("%.6lf
    ",(l+r)/2.0);
    117 }
  • 相关阅读:
    Promise 对象
    [转] LVM分区在线扩容
    [转] 打开 CMD 时自动执行命令
    [转] FFmpeg常用基本命令
    systemd 之 journalctl
    systemd 之 systemctl
    关于用户权限的加强与理解(上)
    [转] 测试环境下将centos6.8升级到centos7的操作记录
    [搞机] 双网卡做数据均衡负载
    [转] 网络基础知识1:集线器,网桥,交换机
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8459541.html
Copyright © 2011-2022 走看看