比赛 4043级2023省选练习赛4 评测结果 AAAAAAAAAA
题目名称 新生舞会 最终得分 100
用户昵称 yrtiop 运行时间 2.730 s
代码语言 C++ 内存使用 4.63 MiB
提交时间 2023-03-10 20:08:14
显示代码纯文本
#include <bits/stdc++.h>

const int maxn = 205;
const int maxm = 5e4 + 5;
const double eps = 1e-7;

double a[maxn][maxn],b[maxn][maxn],w[maxm],dis[maxm],ans,pre[maxn];
bool vis[maxn];
int n,head[maxn],ver[maxm],nxt[maxm],cap[maxm],cnt,S,T,f[maxn];

void add(int u,int v,double t,int c) {
	ver[++ cnt] = v;
	nxt[cnt] = head[u];
	head[u] = cnt;
	w[cnt] = t;
	cap[cnt] = c;
	return ;
}

bool spfa(int s,int t) {
	std::queue<int> q;
	for(int i = 1;i <= t;++ i)
		dis[i] = -0x3f3f3f3f;
	memset(vis , false , sizeof(vis));
	q.push(s);
	dis[s] = 0;
	vis[s] = true;
	f[s] = 0x3f3f3f3f;
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		vis[u] = false;
		for(int i = head[u];~ i;i = nxt[i]) {
			if(!cap[i])
				continue ;
			int v = ver[i];
			if(dis[v] < dis[u] + w[i]) {
				dis[v] = dis[u] + w[i];
				pre[v] = i;
				f[v] = std::min(f[u] , cap[i]);
				if(!vis[v])
					vis[v] = true,q.push(v); 
			}
		}
	}
	if(dis[t] == -0x3f3f3f3f)
		return false;
	return true;
}

void update(int s,int t) {
	int x = t;
	while(x != s) {
		int i = pre[x];
		cap[i] -= f[t];
		cap[i ^ 1] += f[t];
		x = ver[i ^ 1];                                                            
	}
	ans += dis[t] * f[t];
	return ;
}

double calc(double x) {
	memset(head , -1 , sizeof(head));
	cnt = -1;
	ans = 0;
	S = 2 * n + 1;
	T = 2 * n + 2;
	for(int i = 1;i <= n;++ i) {
		add(S , i , 0 , 1);
		add(i , S , 0 , 0);
		add(i + n , T , 0 , 1);
		add(T , i + n , 0 , 0);
	} 
	for(int i = 1;i <= n;++ i)
		for(int j = 1;j <= n;++ j) {
			add(i , j + n , a[i][j] - x * b[i][j] , 1);
			add(j + n , i , -a[i][j] + x * b[i][j] , 0);
		}
	while(spfa(S , T))
		update(S , T);
	return ans;
}

int main() {
	freopen("xswh.in","r",stdin);
	freopen("xswh.out","w",stdout);
	scanf("%d",&n);
	for(int i = 1;i <= n;++ i)
		for(int j = 1;j <= n;++ j)
			scanf("%lf",&a[i][j]);
	for(int i = 1;i <= n;++ i)
		for(int j = 1;j <= n;++ j)
			scanf("%lf",&b[i][j]);
	double l = 0,r = 1e6;
	while(r - l > eps) {
		double mid = (l + r) / 2.0;
		if(calc(mid) >= 0)
			l = mid;
		else
			r = mid;
	}
	printf("%.6lf\n",l);
	return 0;
}