[LOJ][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;
}

posted @ 2018-04-05 13:11  FranceDisco  阅读(230)  评论(0编辑  收藏  举报