zoukankan      html  css  js  c++  java
  • bzoj 4819: [Sdoi2017]新生舞会【二分+最小费用最大流】

    如果( b[i]==0 )那么就是裸的费用流/KM,当然KM快一些但是为什么不写KM呢因为我不会打板子了
    考虑二分答案,那么问题变成了判定问题。

    [ans=frac {a_1+a_2+...+a_n}{b_1+b_2+...+b_n} ]

    [(b_1+b_2+...+b_n)*ans=a_1+a_2+...+a_n ]

    [b_1*ans-a_1+b_2*ans-a_2+...b_n*ans-a_n=0 ]

    然后建立费用流模型,看每次是否( ansleq 0 )即可。
    !:跑spfa时记得初始化为-inf,跑最长路(因为可能是负数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=205,inf=1e9;
    const double eps=1e-7;
    int n,a[N][N],b[N][N],s,t,h[N],cnt,fr[N];
    double dis[N],ans;
    bool v[N];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    struct qwe
    {
        int ne,no,to,va;
        double c;
    }e[N*N];
    void add(int u,int v,int w,double c)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].no=u;
        e[cnt].to=v;
        e[cnt].va=w;
        e[cnt].c=c;
        h[u]=cnt;
    }
    void ins(int u,int v,int w,double c)
    {
        add(u,v,w,c);
        add(v,u,0,-c);
    }
    bool spfa()
    {
        deque<int>q;//因为在洛谷上被卡常所以改成了优化版本(然而还是被KM碾压
        for(int i=s;i<=t;i++)
            dis[i]=-inf;
        dis[s]=0;
        v[s]=1;
        q.push_front(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop_front();
            v[u]=0;
            for(int i=h[u];i;i=e[i].ne)
                if(e[i].va>0&&dis[e[i].to]<dis[u]+e[i].c)
                {
                    dis[e[i].to]=dis[u]+e[i].c;
                    fr[e[i].to]=i;
                    if(!v[e[i].to])
                    {
                        v[e[i].to]=1;
                        if(!q.empty()&&dis[e[i].to]>dis[q.front()])
                            q.push_front(e[i].to);
                        else
                            q.push_back(e[i].to);
                    }
                }
        }
        return dis[t]!=-inf;
    }
    void mcf()
    {
        int x=inf;
        for(int i=fr[t];i;i=fr[e[i].no])
            x=min(x,e[i].va);
        for(int i=fr[t];i;i=fr[e[i].no])
        {
            e[i].va-=x;
            e[i^1].va+=x;
            ans+=x*e[i].c;
        }
    }
    bool ok(double x)
    {
        cnt=1;ans=0;
        memset(h,0,sizeof(h));
        for(int i=1;i<=n;i++)
            ins(s,i,1,0);
        for(int i=1;i<=n;i++)
            ins(i+n,t,1,0);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                ins(i,j+n,1,a[i][j]-x*(double)b[i][j]);
        while(spfa())
            mcf();
        return ans<=0;
    }
    int main()
    {
        n=read();
        t=2*n+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();
        double l=0.0,r=10000.0;
        while(r-l>=eps)
        {
            double mid=(l+r)/2;
            if(ok(mid))
                r=mid;
            else
                l=mid;
        }
        printf("%.6lf",l);
        return 0;
    }
    
  • 相关阅读:
    JAVA中字符串比较equals()和equalsIgnoreCase()的区别
    JAVA字母的大小写转换
    对于java线程的理解
    JAVA实现文件导出Excel
    处理数据库中的null值问题
    POJO、JAVABean、Entity的区别
    Mybatis的choose标签使用
    redis详解
    Spring框架基础解析
    利用 BackgroundService 固定时间间隔执行某动作
  • 原文地址:https://www.cnblogs.com/lokiii/p/8256769.html
Copyright © 2011-2022 走看看