zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8425797.html
Copyright © 2011-2022 走看看