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

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3705 [SDOI2017]新生舞会(分数规划&费用流)相关的知识,希望对你有一定的参考价值。

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

显然二分后,然后就是找 n n n对 满足属性值 ∑ a i , j − m i d × b i , j ≥ 0 \\sum a_{i,j}-mid\\times b_{i,j}\\ge 0 ai,jmid×bi,j0

因为每行每列只有一个点,可以使用费用流,源点与每行流量为1,费用为0,汇点与每列流量为 1,费用为0.

i i i j j j列连边 a i , j − m i d × b i , j a_{i,j}-mid\\times b_{i,j} ai,jmid×bi,j

然后跑最大费用流即可。

// Problem: P3705 [SDOI2017]新生舞会
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3705
// Memory Limit: 250 MB
// Time Limit: 1500 ms
// Date: 2021-08-23 14:46:43
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=105,M=205,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int cnt=1,h[M],flow[M],vis[M],n,m,st,ed;
double dis[M];
ll mf;
double mc;
int id(int x,int y){
	return (x-1)*n+y;
}
queue<int>q;
struct edge{
	int to,nt;
	int f;
	double w;//f:flow ,w:cost 
}e[M*M*4];
struct Pre{
	int i,u;
}pre[M*M*4];//记录前驱结点和边的信息,便于更新残余网络,建立反边.(反悔和贪心的思想)	
void add(int u,int v,int f,double w){
	e[++cnt]={v,h[u],f,w},h[u]=cnt;
	e[++cnt]={u,h[v],0,-w},h[v]=cnt;
} 
bool spfa(){// 跑spfa 
	for(int i=st;i<=ed;i++) dis[i]=-1e18;
	mst(flow,0x3f),mst(vis,0);	//初始化. 
	q.push(st),vis[st]=1,dis[st]=0,pre[ed].u=-1;//预处理 
	while(!q.empty()){
		int u=q.front();q.pop();vis[u]=0;
		for(int i=h[u];i;i=e[i].nt){
			int v=e[i].to;
			int f=e[i].f;
			double w=e[i].w;
			if(f>0&&dis[v]<dis[u]+w){
				dis[v]=dis[u]+w;
				pre[v].u=u,pre[v].i=i;
				flow[v]=min(flow[u],f);
				if(!vis[v]) vis[v]=1,q.push(v);
			}
		}
	}
	return pre[ed].u!=-1;
}
void MCMF(){	//MIncost Maxflow 
	while(spfa()){
		int u=ed,x=flow[ed];
		mf+=x;
		mc+=x*dis[u];
		while(u!=st){
			e[pre[u].i].f-=x;
			e[pre[u].i^1].f+=x;
			u=pre[u].u;
		}
	}
}
int A[N][N],B[N][N];
bool ck(double x){
	cnt=1,mst(h,0);
	for(int i=1;i<=n;i++)
		add(st,i,1,0),add(i+n,ed,1,0);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			add(i,j+n,1,A[i][j]-x*B[i][j]);
	mc=mf=0;
	MCMF();return mc>=0;
}
const double eps=1e-8;
int main(){
	scanf("%d",&n);st=0,ed=(n<<1)+1;
	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,r=1e4;
	while(r-l>eps){
		double mid=(l+r)/2.0;
		if(ck(mid)) l=mid;
		else r=mid;
	}
	printf("%.6f\\n",l);
	return 0;
}

以上是关于P3705 [SDOI2017]新生舞会(分数规划&费用流)的主要内容,如果未能解决你的问题,请参考以下文章

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

BZOJ_4819_[Sdoi2017]新生舞会_01分数规划+费用流

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

BZOJ.4819.[SDOI2017]新生舞会(01分数规划 费用流SPFA)

[SDOI2017]新生舞会

codevs 5965 [SDOI2017]新生舞会