分析

做了几道分数规划题,选一些来写题解。

首先观察答案形式,就是求最终 \((\dfrac{\sum a_i'}{\sum b_i'})\geqslant ans\) 最大的 \(ans\),在转化一下形式,就是 \(\sum a_i'-ans\times b_i'\geqslant 0\)

所以我们去二分答案(显然越小的答案最终越容易使上面式子满足),然后每一组对答案的贡献就能计算出,然后又要求每一个人都要找到各自舞伴,式子中的大于等于可以视为使左边的值最大,所以在 check 函数中我们男女生建点,每一组的贡献用作建边,男生向女生建边,流量为 \(1\),费用 \(a[i][j]-mid\times b[i][j]\),超级源点向男生,女生向超级汇点建流量 \(1\),费用 \(0\) 的边,验证最大费用是否大于等于 \(0\) 即可。

代码

#include<bits/stdc++.h>
using namespace std;
inline void read(int &res){
	res=0;
	int f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
	res*=f;
}
int n,s,t;
int a[105][105];
int b[105][105];
int head[210],tot;
struct edge{
	int to,nex,w;
	double bq;
}e[100000];
inline void add(int qq,int mm,int w,double bq){
	e[++tot].to=mm;
	e[tot].nex=head[qq];
	e[tot].w=w;
	e[tot].bq=bq;
	head[qq]=tot;
}
double dis[210];
int pre[210],incf[210];
queue<int>q;
int vis[210];
bool spfa(){
	for(int i=1;i<=t;i++){
		dis[i]=-1e18;
		incf[i]=1e9;
	}
	q.push(s);
	while(q.size()){
		int x=q.front();q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=e[i].nex){
			if(!e[i].w)continue;
			int v=e[i].to;
			if(dis[v]<dis[x]+e[i].bq){
				pre[v]=i;
				dis[v]=dis[x]+e[i].bq;
				incf[v]=min(incf[v],e[i].w);
				if(!vis[v])q.push(v);
				vis[v]=1;
			}
		}
	}
	return incf[t]<1e9;
}
bool check(double x){
	memset(head,0,sizeof(head));
	tot=1;
	for(int i=1;i<=n;i++){
		add(0,i,1,0);
		add(i,0,0,0);
		for(int j=1;j<=n;j++){
			double bq=-x*b[i][j]+a[i][j];
			add(i,j+n,1,bq);
			add(j+n,i,0,-bq);
		}
		add(i+n,t,1,0);
		add(t,i+n,0,0);
	}
	double sum=0;
	while(spfa()){
		sum+=incf[t]*dis[t];
		int x=t;
		while(x!=s){
			e[pre[x]].w--;
			e[pre[x]^1].w++;
			x=e[pre[x]^1].to;
		}
	}
	return sum>=0;
}
int main()
{
	read(n);
	s=0;t=2*n+1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)read(a[i][j]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)read(b[i][j]);
	}
	double l=0,r=10000;
	while(r-l>=1e-7){
		double mid=(l+r)/2.0;
		if(check(mid))l=mid+1e-8;
		else r=mid-1e-8;
	}
	printf("%.6lf",l);
}

posted on 2021-12-16 15:26  漠寒·  阅读(28)  评论(0编辑  收藏  举报