[Libre][SDOI2017]新生舞会

Posted notseefire

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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;
}

以上是关于[Libre][SDOI2017]新生舞会的主要内容,如果未能解决你的问题,请参考以下文章

[Sdoi2017]新生舞会

SDOI2017 新生舞会

[BZOJ4819][SDOI2017]新生舞会

[SDOI2017]新生舞会

[BZOJ]4819: [Sdoi2017]新生舞会

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