zoukankan      html  css  js  c++  java
  • Luogu-3705 [SDOI2017]新生舞会

    分数规划,最大费用最大流#

    题意可以简化为给出一个矩阵,要求每行和每列必须且只能取一个格子,要求(sigma a_{i,j}/sigma b_{i,j}) 最大

    考虑分数规划,可以将式子转化:

    (sigma a_{i,j}/sigma b_{i,j}=C)

    (sigma a_{i,j}=sigma b_{i,j}*C)

    (sigma a_{i,j}-sigma b_{i,j}*C=0)

    (sigma( a_{i,j}-b_{i,j}*C)=0)

    C就是我们要求的最大值,我们可以(mid)实数二分它,对于每一个(mid),求出这种情况下(sigma( a_{i,j}-b_{i,j}*mid)=0)的最大值,如果最大值小于0,就说明(mid>C),反之亦然。

    至于怎么求最大值,可以将横坐标建一个点集,纵坐标建一个点集,对于每个矩阵上的点(a_{i,j})建一条从i到j的弧,流量为1,费用为(a_{i,j}-sigma b_{i,j}*mid),然后跑最大费用最大流就行了

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<map>
    #define inf 0x7fffffff
    using namespace std;
    inline int read()
    {
    	int ans=0,fh=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	return ans*fh;
    }
    const int maxn=300;
    const int maxm=10010;
    const double eps=0.00000001;
    int s,t,v[maxm*2],u[maxm*2],w[maxm*2],qq[maxn],ll[maxn],nex[maxm*2],head[maxn],num=1,n,a[110][110],b[110][110];
    double f[maxm*2],bj[maxn],l,r,mid;
    bool cz[maxn];
    queue<int>q;
    void add(int x,int y,double fee)
    {
    	u[++num]=x;
    	v[num]=y;
    	w[num]=1;
    	f[num]=fee;
    	nex[num]=head[x];
    	head[x]=num;
    	u[++num]=y;
    	v[num]=x;
    	w[num]=0;
    	f[num]=-fee;
    	nex[num]=head[y];
    	head[y]=num;
    }
    bool spfa()
    {
    	memset(qq,0,sizeof(qq));
    	for(int i=1;i<=n*2+2;i++)
    		bj[i]=2100000000;
    	memset(ll,0,sizeof(ll));
    	q.push(s);
    	bj[s]=0;
    	ll[s]=inf;
    	while(!q.empty())
    	{
    		int now=q.front();
    		q.pop();
    		cz[now]=0;
    		for(int i=head[now];i;i=nex[i])
    			if(w[i]&&bj[v[i]]>bj[now]+f[i])
    			{
    				bj[v[i]]=bj[now]+f[i];
    				ll[v[i]]=min(w[i],ll[now]);
    				qq[v[i]]=i;
    				if(!cz[v[i]])
    					q.push(v[i]),cz[v[i]]=1;
    			}
    	}
    	return qq[t]>0;
    }
    double EK()
    {
    	double fee=0;
    	while(spfa())
    	{
    		int liu=ll[t];
    		for(int i=qq[t];i;i=qq[u[i]])
    			w[i]-=liu,w[i^1]+=liu;
    		fee+=liu*bj[t];
    	}
    	return fee*-1;
    }//最大费用最大流
    double work(double x)
    {
    	memset(head,0,sizeof(head));
    	num=1;
    	for(int i=1;i<=n;i++)
    		add(s,i,0),add(i+n,t,0);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			add(i,j+n,(double)x*b[i][j]-a[i][j]);//建图
    	return EK();
    }
    int main()
    {
    	n=read();
    	s=n*2+1;t=s+1;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			a[i][j]=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			b[i][j]=read();
    	r=1000000;
    	while(r-l>eps)
    	{
    		mid=(l+r)*0.5;
    		double dd=work(mid);
    		if(dd>=0)
    			l=mid;
    		else
    			r=mid;
    	}//实数二分
    	printf("%.6lf",l);
    	fclose(stdin);
    	return 0;
    }
    
    
  • 相关阅读:
    Session的使用与Session的生命周期
    Long-Polling, Websockets, SSE(Server-Sent Event), WebRTC 之间的区别与使用
    十九、详述 IntelliJ IDEA 之 添加 jar 包
    十八、IntelliJ IDEA 常用快捷键 之 Windows 版
    十七、IntelliJ IDEA 中的 Maven 项目初体验及搭建 Spring MVC 框架
    十六、详述 IntelliJ IDEA 创建 Maven 项目及设置 java 源目录的方法
    十五、详述 IntelliJ IDEA 插件的安装及使用方法
    十四、详述 IntelliJ IDEA 提交代码前的 Code Analysis 机制
    十三、IntelliJ IDEA 中的版本控制介绍(下)
    十二、IntelliJ IDEA 中的版本控制介绍(中)
  • 原文地址:https://www.cnblogs.com/nianheng/p/9814480.html
Copyright © 2011-2022 走看看