zoukankan      html  css  js  c++  java
  • bzoj 4819: [Sdoi2017]新生舞会

    题目链接

    bzoj4819: [Sdoi2017]新生舞会

    题解

    很裸的01分规,化完式子大概是这样的
    $ sum ai - sum bi *C$
    二分最大比值C建图,
    当最大费用 >=0 时,二分下界调大
    否则上界调小
    在洛谷似乎有些卡常,但借助bzoj的总时限还是跑过去了

    然而开始的时候我是用$ sum bi *C-sum ai $这个式子做的
    然后GG...调不动了.....重打

    代码

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define eps 1e-7
    using std::queue;
    inline int read() {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
        while (c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    const int maxn = 307;
    int n;
    double a[maxn][maxn];
    double b[maxn][maxn];
    struct node{
        int flow,u,v,next;double cost;
    }edge[maxn*maxn*3];
    int num=1,head[maxn<<1],S,T,tmp;
    inline void add_edge(int u,int v,int flow,double cost) {
        edge[++num].u = u;edge[num].v = v;edge[num].flow = flow;edge[num].cost = cost,edge[num].next = head[u];head[u] = num;
    }
    inline void ADD(int u,int v,int flow,double cost) { add_edge(u,v,flow,cost); add_edge(v,u,0,-cost); }
    void rebuild(double C) {
        num=1;
        memset(head,0,sizeof head);
        for (int i = 1;i <= n;++i) 
            ADD(S,i,1,0), ADD(n + i,T,1,0);
        for (int i = 1;i <= n;++ i)  for (int j = 1;j <= n;++ j) 
                ADD(i,n + j,1, a[i][j]-b[i][j]*C);
    }
    
    double dis[maxn<<2];int pre[maxn<<2];bool vis[maxn<<2]; 
    bool spfa() {
        queue<int>q;
        for(int i=S;i<=T;++i) dis[i]=-0x3f3f3f3f,pre[i]=0;
        memset(vis,0,sizeof vis);
        q.push(S);vis[S] = true;dis[S] = 0;
        while (!q.empty()) {
            int u = q.front();q.pop();
            for (int v,i = head[u];i;i = edge[i].next) {
                v = edge[i].v;
                if (edge[i].flow > 0&&dis[v] < dis[u] + edge[i].cost) {
                    pre[v] = i;
                    dis[v] = dis[u] + edge[i].cost;
                    if (!vis[v]) q.push(v),vis[v] = 1;
                }
            }
            vis[u] = 0;
        }
        return dis[T] != -0x3f3f3f3f;
    }
    
    double calc() {
        double ret = 0;int MF = 0x3f3f3f3f;
        for (int i = T;i != S;i = edge[pre[i]].u) 
            MF = std::min(edge[pre[i]].flow,MF);
        for (int i = T;i != S;i = edge[pre[i]].u) {
            edge[pre[i]].flow -= MF;
            edge[pre[i]^1].flow += MF;
            ret += edge[pre[i]].cost * 1.0*MF;
        }
        return ret;
    }
    
    double mfmc() {
        double ret=0;
        while(spfa()) 
        ret += calc();
        return ret;
    }
    
    bool check() { return mfmc()>=0 ? true : false ;   }
    
    int main() {
        n = read();
        S = 0,T = n*2+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();
        //printf("%lf %lf
    ",dis[0],0x3f3f3f3f);
        double l=0,r=1000009.0;
        while(r - l > eps) {
            double mid = (l + r) / 2;
            rebuild(mid);
            if(check()) l=mid;
            else r=mid;
        }
        printf("%lf
    ",l);
        return 0;
    }
    
    
  • 相关阅读:
    [MFC] MFC 用mciSendString加载WAV资源文件
    [JS] HTML QQ分享界面js代码
    [MFC] MFC 打开HTML资源(用ID版,也可加载到自己的web控件上)
    [ACM_暴力][ACM_几何] ZOJ 1426 Counting Rectangles (水平竖直线段组成的矩形个数,暴力)
    [ACM_动态规划] ZOJ 1425 Crossed Matchings(交叉最大匹配 动态规划)
    easyui combobox可编辑的情况下,只能首字母开始过滤的问题选项
    easyui-combobox绑定回车事件注意事项
    easyui-combobox绑定回车事件相关
    jquery-qrcode 生成和读取二维码
    zxing生成二维码和读取二维码
  • 原文地址:https://www.cnblogs.com/sssy/p/8659571.html
Copyright © 2011-2022 走看看