[Libre][SDOI2017]新生舞会

分数规划模板题 , 会写就能A



#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<cstdio>

using namespace std;
typedef long long ll;
const int N = 105 << 1 , Mod = 998244353 , G = 3 , INF = 0x3f3f3f3f;
double PI = acos(-1) , eps = 1e-7;

struct Virt{
    double x , y;
    Virt(double _x = 0.0 , double _y = 0.0):x(_x) , y(_y){}
};

Virt operator + (Virt x , Virt y){return Virt(x.x + y.x , x.y + y.y);}
Virt operator - (Virt x , Virt y){return Virt(x.x - y.x , x.y - y.y);}
Virt operator * (Virt x , Virt y){return Virt(x.x * y.x - x.y * y.y , x.x * y.y + x.y * y.x);}

int read(){
    int x = 0 , f = 1; char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘){if(ch == ‘-‘) f = -1 ; ch = getchar();}
    while(ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘; ch = getchar();}
    return x * f;
}

struct edge{
    int pos , nx , cap;
    double cost;
}e[(N * N) << 1];

int n , num , a[N][N] , b[N][N] , head[N];

void add(int u , int v , int c , double w){
    e[++num].pos = v; e[num].cap = c; e[num].cost = w; e[num].nx = head[u]; head[u] = num;
    e[++num].pos = u; e[num].cap = 0; e[num].cost = -w; e[num].nx = head[v]; head[v] = num;
}

struct mcfx{
    double d[N];
    int s , t , pre[N];
    bool inq[N];

    bool SPFA(){
        memset(pre , 0 , sizeof(pre));
        for(int i = 1 ; i <= t ; i++) d[i] = -1.0;
        queue<int> q;
        d[s] = 0.0 , q.push(s);
        while(!q.empty()){
            int now = q.front(); q.pop(); inq[now] = false;
            for(int i = head[now] ; i ; i = e[i].nx){
                if(e[i].cap > 0 && d[e[i].pos] < d[now] + e[i].cost){
                    d[e[i].pos] = d[now] + e[i].cost;
                    pre[e[i].pos] = i;
                    if(!inq[e[i].pos]){
                        inq[e[i].pos] = true;
                        q.push(e[i].pos);
                    }
                }
            }
        }
        return d[t] != -1.0;
    }

    double Calc(){
        int flow;
        double ans = 0;
        while(SPFA()){
            flow = INF;
            for(int i = t ; i != s ; i = e[pre[i] ^ 1].pos) flow = min(flow , e[pre[i]].cap);
            for(int i = t ; i != s ; i = e[pre[i] ^ 1].pos) e[pre[i]].cap -= flow , e[pre[i] ^ 1].cap += flow;
            ans += d[t] * flow;
        }
        return ans;
    }

    void init(double mid){
        num = 1;
        memset(head , 0 , sizeof(head));
        for(int i = 1 ; i <= n ; i++)
            add(s , i , 1 , 0) , add(i + n , t , 1 , 0);
        for(int i = 1 ; i <= n ; i++)
            for(int j = 1 ; j <= n ; j++)
                add(i , j + n , 1 , (double)a[i][j] - mid * b[i][j]);
    }

}netflow;

int main(){
    scanf("%d",&n);
    for(int i = 1 ; i <= n ; i++)
        for(int j = 1 ; j <= n ; j++)
            scanf("%d",&a[i][j]);
    for(int i = 1 ; i <= n ; i++)
        for(int j = 1 ; j <= n ; j++)
            scanf("%d",&b[i][j]);
    double l = 0.0 , r = 1000005.0 , ans;
    netflow.s = n * 2 + 1 , netflow.t = n * 2 + 2;
    while(abs(r - l) > eps){
        double mid = (r + l) * 0.5;
        netflow.init(mid);
        if(netflow.Calc() > eps) ans = mid , l = mid + eps;
        else r = mid - eps;
    }
    printf("%lf",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/notseefire/p/8722177.html

时间: 2024-10-06 10:53:53

[Libre][SDOI2017]新生舞会的相关文章

[Sdoi2017]新生舞会

[Sdoi2017]新生舞会 http://www.lydsy.com/JudgeOnline/problem.php?id=4819 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算

[BZOJ4819][SDOI2017]新生舞会

[BZOJ4819][SDOI2017]新生舞会 bzoj luogu 题意 有\(n\)个男孩子和\(n\)个女孩子.他们之间要两两结伴跳舞. 已知第\(i\)个男孩子和第\(j\)个女孩子结伴跳舞会有两个参数\(a_{i,j}\)和\(b_{i,j}\). 现在要求一个安排方案使得\(a_{i,j}\)的总和除以\(b_{i,j}\)的总和的商尽量大. 形式化地,就是求一个长度为\(n\)的排列\(\{p_i\}\),最大化\(L=\frac{\sum_{i=1}^{n}a_{i,p_i}}

bzoj 4819: [Sdoi2017]新生舞会

Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy还需要考虑两个人一起跳舞是否方便, 比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度.当然, 还需要考虑很多其他问题.Cathy

【bzoj4819】[Sdoi2017]新生舞会 分数规划+费用流

题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy还需要考虑两个人一起跳舞是否方便,比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度.当然,还需要考虑很多其他问题.Cathy想先用一个程序通过a

BZOJ4819: [Sdoi2017]新生舞会(01分数规划)

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1029  Solved: 528[Submit][Status][Discuss] Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy

codevs 5965 [SDOI2017]新生舞会

分数规划的裸题. 不会分数规划的OIer.百度:胡伯涛<最小割模型在信息学竞赛中的应用> /* TLE1: last:add(i,j+n,1e9,(real)((real)a[i][j]-ans*(real)b[i][j])); now :add(i,j+n,1,(real)((real)a[i][j]-ans*(real)b[i][j])); TLE2: last:real l=eps,r=(real)u/(real)v,mid,ans=0,now; now :real l=0,r=(rea

4819: [Sdoi2017]新生舞会

题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4819 思路 分数规划的模板题?(好菜呀) 假如n=3吧(懒得写很长的式子) \(c=\frac{a_1+a_2+a_3}{b_1+b_2+b_3}\) 我们先二分一下,变为判定性问题 c是否大于等于xxxx \(c>=\frac{a_1+a_2+a_3}{b_1+b_2+b_3}\) \((b_1+b_2+b_3)*c>=a_1+a_2+a_3\) \(0>=(a_1-c*b_1)

P3705 [SDOI2017]新生舞会 分数规划 费用流

#include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #incl

BZOJ4819 新生舞会

4819: [Sdoi2017]新生舞会 Time Limit: 10 Sec  Memory Limit: 128 MB Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy还需要考虑两个人一起跳舞是否方便, 比如身高体重差别会不会