zoukankan      html  css  js  c++  java
  • 4819: [Sdoi2017]新生舞会 分数规划

    题目

    https://www.lydsy.com/JudgeOnline/problem.php?id=4819

    思路

    分数规划的模板题?(好菜呀)
    假如n=3吧(懒得写很长的式子)
    (c=frac{a_1+a_2+a_3}{b_1+b_2+b_3})
    我们先二分一下,变为判定性问题
    c是否大于等于xxxx
    (c>=frac{a_1+a_2+a_3}{b_1+b_2+b_3})
    ((b_1+b_2+b_3)*c>=a_1+a_2+a_3)
    (0>=(a_1-c*b_1)+(a_2-c*b_2)+(a_3-c*b_3))
    取反跑费用流就好了
    每次cnt没=1,居然T了
    说:没油圈就可以取反跑费用流

    代码

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N = 5e5 + 7,inf=0x3f3f3f3f;
    const double eps=1e-7;
    int read() {
        int x=0,f=1;char s=getchar();
        for (;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
        for (;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
        return x*f;
    }
    int n,S,T;
    int a[120][119],b[110][120];
    struct node {
    	int u,v,nxt,cap;
    	double cost;
    }e[N];
    int head[N],cnt=1;
    void add_edge(int u,int v,int cap,double cost) {
    	e[++cnt].v=v;
    	e[cnt].u=u;
    	e[cnt].cap=cap;
    	e[cnt].cost=cost;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    void Add(int u,int v,int cap,double cost) {
    	add_edge(u,v,cap,cost);
    	add_edge(v,u,0,-cost);
    }
    double dis[1001];
    int frm[1001];
    bool vis[1001];
    queue<int> q;
    bool spfa() {
    	for(int i=0;i<=n+n;++i) dis[i]=-inf;
    	dis[T]=-inf;
    	memset(vis,0,sizeof(vis));
    	memset(frm,0,sizeof(frm));
    	q.push(S);
    	dis[S]=0;
    	while(!q.empty()) {
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=head[u];i;i=e[i].nxt) {
    			int v=e[i].v;
    			if(e[i].cap&&dis[v]<dis[u]+e[i].cost) {
    				dis[v]=dis[u]+e[i].cost;
    				frm[v]=i;
    				if(!vis[v]) vis[v]=1,q.push(v);
    			}
    		}
    	}
    	return dis[T]!=-inf;
    }
    double work() {
    	double ans=0;
    	while(spfa()) {
    		int now_flow=inf;
    		for(int i=frm[T];i;i=frm[e[i].u])
    			now_flow=min(now_flow,e[i].cap);
    		for(int i=frm[T];i;i=frm[e[i].u]) {
    			e[i].cap-=now_flow;
    			e[i^1].cap+=now_flow;
    			ans+=now_flow*e[i].cost;
    		}
    	}
    	return ans;
    }
    bool check(double c) {
    	memset(e,0,sizeof(e));
    	memset(head,0,sizeof(head));
    	cnt=1;
    	S=2*n+1,T=2*n+2;
    	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,a[i][j]-c*b[i][j]);
    	double tmp=work();
    	return tmp>=eps;//精度高了,等不等号差不多了
    }
    int main() {
    	//read
    	n=read();
    	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();
    	double l=0,r=1e4+1,ans=0;
    	while(r-l>=eps) {
    		double mid=(l+r)/2;
    		if(check(mid)) ans=mid,l=mid;
    		else r=mid;
    	}
    	printf("%.6lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    linux系统下MySQL表名区分大小写问题
    linux下查看Mysql默认编码、修改默认编码
    mysql的下载及安装(windows)
    数据库进阶
    mysql练习
    数据库基础
    jQuery
    JavaScript 基础学习(二)
    344.Reverse String
    计蒜客课程数据结构(顺序表)
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10387145.html
Copyright © 2011-2022 走看看