• 【Luogu】P3705新生舞会(费用流+分数规划+二分答案)


      题目链接

      本来以为自己可以做出来,结果……打脸了

      (貌似来wc立了好几个flag了,都没竖起来)

      不过乱蒙能蒙出一个叫“分数规划”的东西的式子还是很开心的

      观察$C=frac{a_{1}+a_{2}+.......+a_{n}}{b_{1}+b_{2}+.....b_{n}}$

      然后可以把分母乘到左边

      然后可以把C乘进去

      然后二分C,建图求最大权匹配,判断跟答案的关系。

      

    #include<cstdio>
    #include<cstdlib>
    #include<cctype>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #define maxn 450
    #define eps 1e-7
    using namespace std;
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='0')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int from,next,to,val;
        double dis;
    }edge[maxn*maxn*3];
    int head[maxn],num;
    inline void addedge(int from,int to,int val,double dis){
        edge[++num]=(Edge){from,head[from],to,val,dis};
        head[from]=num;
    }
    inline void add(int from,int to,int val,double dis){
        addedge(from,to,val,dis);
        addedge(to,from,0,-dis);
    }
    inline void clear(){    memset(head,0,sizeof(head));    num=0;    }
    inline int count(int i){    return i&1?i+1:i-1;    }
    
    double dis[maxn];
    int pre[maxn];
    int flow[maxn];
    bool vis[maxn];
    int d[maxn][maxn];
    int w[maxn][maxn];
    int Start,End;
    int n;
    
    double spfa(){
        for(int i=Start;i<=End;++i)    dis[i]=-0x7fffffff; dis[Start]=0;
        queue<int>q; q.push(Start);    memset(flow,0,sizeof(flow)); flow[Start]=0x7fffffff;
        while(!q.empty()){
            int from=q.front();    q.pop();    vis[from]=0;
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(edge[i].val<=0||dis[to]>=dis[from]+edge[i].dis)    continue;
                dis[to]=dis[from]+edge[i].dis;
                pre[to]=i;    flow[to]=min(flow[from],edge[i].val);
                if(vis[to])    continue;
                vis[to]=1;    q.push(to);
            }
        }
        if(flow[End]==0)    return 0;
        int now=End;
        while(now!=Start){
            //printf("D");
            int i=pre[now];
            edge[i].val-=flow[End];
            edge[count(i)].val+=flow[End];
            now=edge[i].from;
        }
        return dis[End];
    }
    
    bool payflow(double lim){
        clear();
        for(int i=1;i<=n;++i){
            add(Start,i,1,0);
            add(i+n,End,1,0);
        }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)    add(i,j+n,1,1.0*d[i][j]-1.0*w[i][j]*lim);
        double ret=0;
        while(1){
            double now=spfa();
            if(fabs(now)<=eps)    break;
            ret+=now;
        }
        return ret>0;
    }
    
    int main(){
        n=read();    End=n*2+1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)    d[i][j]=read();
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)    w[i][j]=read();
        double l=0,r=1e4;double ans=0;
        while(r-l>eps){
            double mid=(l+r)/2.0;
            if(payflow(mid)){
                ans=mid;
                l=mid;
            }
            else    r=mid;
        }
        printf("%.6lf",ans);
        return 0;
    }
  • 相关阅读:
    Paragon NTFS for Mac免费获取官方赠送正版.更新获取ntfs for mac 14方法
    Python修饰器的函数式编程
    Python装饰器与面向切面编程
    linux配置IP的方法
    Centos搭建SVN服务器三步曲
    [CentOS 6.5 X64]讓firefox java plugin 啟動
    逻辑分析题(三)
    逻辑分析题汇总(一)
    第十章—DOM(0)—NODE类型
    第十章—DOM(三)——Text类型
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8425797.html
Copyright © 2020-2023  润新知