zoukankan      html  css  js  c++  java
  • 洛谷3705 [SDOI2017] 新生舞会 【01分数规划】【KM算法】

    题目分析:

    裸题。怀疑$ O(n^4log{n}) $跑不过,考虑Edmonds-Karp优化。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn =  120;
     5 
     6 const double eps = 1e-7;
     7 
     8 int n;
     9 
    10 int a[maxn][maxn],b[maxn][maxn];
    11 
    12 double lx[maxn],ly[maxn],c[maxn][maxn];
    13 int inS[maxn],inT[maxn],Left[maxn];
    14 double slack[maxn];
    15 
    16 void read(){
    17     scanf("%d",&n);
    18     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
    19     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&b[i][j]);
    20 }
    21 
    22 int match(int now){
    23     inS[now] = 1;
    24     for(int i=1;i<=n;i++){ 
    25     if(inT[i]) continue;
    26     if(lx[now]+ly[i] - c[now][i] <= eps){
    27         inT[i] = 1;
    28         if(!Left[i] || match(Left[i])){
    29         Left[i] = now;
    30         return true;
    31         }
    32     }else slack[i] = min(slack[i],lx[now]+ly[i]-c[now][i]);
    33     }
    34     return false;
    35 }
    36 
    37 void update(){
    38     double pp = 1e9;
    39     for(int i=1;i<=n;i++) if(!inT[i]) pp = min(pp,slack[i]);
    40     for(int i=1;i<=n;i++){
    41     if(inS[i]) lx[i] -= pp;
    42     if(inT[i]) ly[i] += pp;
    43     else slack[i] -= pp;
    44     }
    45 }
    46 
    47 bool KM(double now){
    48     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) c[i][j] = a[i][j]-now*b[i][j];
    49     for(int i=1;i<=n;i++) {
    50     lx[i] = -1E9,ly[i] = 0; Left[i] = 0;
    51     for(int j=1;j<=n;j++) lx[i] = max(lx[i],c[i][j]);
    52     }
    53     for(int i=1;i<=n;i++){
    54     for(int j=1;j<=n;j++) slack[j] = 1e9;
    55     for(;;){
    56         for(int j=1;j<=n;j++) inS[j] = inT[j] = 0;
    57         if(match(i)) break;
    58         update();
    59     }
    60     }
    61     double ans = 0;
    62     for(int i=1;i<=n;i++) ans += lx[i] + ly[i];
    63     if(ans <0) return false;
    64     else return true;
    65 }
    66 
    67 double divide(double l,double r){
    68     if(r-l <= eps) return l;
    69     double mid = (l+r)/2.0;
    70     int flag = KM(mid);
    71     if(flag) return divide(mid,r);
    72     else return divide(l,mid);
    73 }
    74 
    75 int main(){
    76     read();
    77     printf("%.6lf",divide(0,1E4));
    78     return 0;
    79 }
  • 相关阅读:
    C & 指针
    分析Android (build/core/*.mk脚本)
    C#.net调用axis2webService
    MongoDB 配置文件启动
    mongodb 简单部署方案及实例
    MongoDB 权限认证
    MongoDB索引介绍
    mongodb 全文检索
    MongoDB 覆盖索引查询
    mongodb MongoDB 聚合 group
  • 原文地址:https://www.cnblogs.com/Menhera/p/9117690.html
Copyright © 2011-2022 走看看