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;
    }
    
  • 相关阅读:
    二分图最大匹配的K&#246;nig定理及其证明
    HDOJ 2389 Rain on your Parade
    HDOJ 1083 Courses
    HDOJ 2063 过山车
    POJ 1469 COURSES
    UESTC 1817 Complete Building the Houses
    POJ 3464 ACM Computer Factory
    POJ 1459 Power Network
    HDOJ 1532 Drainage Ditches
    HDU 1017 A Mathematical Curiosity
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10387145.html
Copyright © 2011-2022 走看看