zoukankan      html  css  js  c++  java
  • 提交答案题(网络流)

    提交答案题(网络流)

    计算一次函数的值实在是太难了,所以为了简化问题,我们计算二次函数。现在给了你(N)个二次函数,第(i)个二次函数的形状为(f_i(x_i) = a_i {x_i}^2 + b_i x_i + c_i , l_i leq x_i leq r_i)。同时我们又给了你(M)个限制关系,限制关系的形式为(x_u leq x_v + d)。现在告诉你所有这些信息,你需要最大化(sum_{i = 1}^{N} f_i(x_i))的值。

    (1 leq N leq 50 , 0 leq M leq 100 , |a_i| leq 10 , |b_i| , |c_i| leq 1000 , −100 leq l_i leq r_i leq 100 , 1 leq u , v leq N , u eq v , |d| leq 200)

    听说这种坐标限制相关的题目都可以用网络流,与二次函数无关?

    对于每个二次函数的区间,把所有区间上的整点都建在网络流的点上,依次连接(同时头要向src,为要向dst连接),一个点(x_iin[l_{now}, r_{now}])的值是(f_{now}(x_i))的值。那么一个区间就构成了一条链。如果不考虑限制,网络流这样跑出来就是正确的。

    由于有坐标限制,例如(x_u<x_v+d)。考虑这个式子的含义,意思是说,如果选定了(x_v)的一个值a,那么必须满足(x_v>a-d)。因此用网络流在两个链上连若干INF边即可。

    这个做法的点数是(n*200=1e4),边数是(1e4+M*200=3e4)。用dinic是能过的~

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxf=55, maxn=maxf*200, maxm=maxn+100, INF=1e9, inf=1e8;
    int n, m, cnt, src, dst, ans;
    inline int min(int x, int y){ return x<y?x:y; }
    struct Edge{
        int to, nxt, f;
    }e[maxm*2];
    int fir[maxn], cnte=1;
    void addedge(int x, int y, int v){
        Edge &ed=e[++cnte];
        //printf("%d %d
    ", x, y);
        ed.to=y; ed.nxt=fir[x]; ed.f=v; fir[x]=cnte;
    }
    int q[maxn], head, tail, dep[maxn];
    bool bfs(){
        memset(dep, 0, sizeof(dep)); dep[src]=1;
        head=tail=0; q[tail++]=src; int u;
        while (head<tail){
            u=q[head++];
            for (int i=fir[u]; i; i=e[i].nxt)
                if (e[i].f&&!dep[e[i].to]){
                    dep[e[i].to]=dep[u]+1;
                    q[tail++]=e[i].to;
                }
        }
        return dep[dst];
    }
    int cur[maxn];
    int dfs(int u, int flow){
        if (u==dst) return flow;
        for (int i=cur[u]; i; i=e[i].nxt, cur[u]=i)
        if (dep[e[i].to]==dep[u]+1&&e[i].f){
            int minm=dfs(e[i].to, min(flow, e[i].f));
            e[i].f-=minm; e[i^1].f+=minm;
            if (minm) return minm;
        }
        return 0;
    }
    int Dinic(){
        int ans=0, t;
        while (bfs()){
            memcpy(cur, fir, sizeof(fir));
            while (t=dfs(src, INF)) ans+=t;
        }
        return ans;
    }
    
    int a[maxf], b[maxf], c[maxf], l[maxf], r[maxf];
    int beg[maxn];  //代表第i个函数的起始点编号
    
    int main(){
        int u, v, d;
        scanf("%d%d", &n, &m); src=++cnt; dst=++cnt; int val;
        for (int i=0; i<n; ++i) scanf("%d%d%d", &a[i], &b[i], &c[i]);
        for (int i=0; i<n; ++i){
            scanf("%d%d", &l[i], &r[i]);
            addedge(src, ++cnt, 2*inf);
            addedge(cnt, src, 0);
            beg[i]=cnt;
            for (int j=l[i]; j<=r[i]; ++j){
                val=a[i]*j*j+b[i]*j+c[i];
                addedge(cnt, cnt+1, inf-val);
                addedge(cnt+1, cnt, 0);
                ++cnt;
            }
            addedge(cnt, dst, 2*inf);
            addedge(dst, cnt, 0);
        } int x, y;
        while (m--){
            scanf("%d%d%d", &u, &v, &d); --u; --v;
            for (int i=l[v]; i<=r[v]; ++i){
                int j=i+d;
                if (j>r[u]) continue;
                //beg[u]+j-l[u]表示x[u]=x[v]+d的点的编号
                x=beg[u]+max(0, j-l[u]+1); y=beg[v]+i-l[v]+1;
                addedge(x, y, 2*inf); addedge(y, x, 0);
            }
        }
        printf("%d
    ", inf*n-Dinic());
        return 0;
    }
    
  • 相关阅读:
    STM32 之 USB IP(USB模块) 详解(转)
    USB 协议分析之 HID 设备(转)
    Hibernate项目用Maven创建(转)
    eclipse查看hadoop中文件出现乱码
    用spring+hibernate+struts 项目记录以及常用的用法进等
    hibernate之处理视图
    Hadoop组件之-HDFS(HA实现细节)
    hadoop2.x NameNode 的共享存储实现
    Hadoop-2.X HA模式下的FSImage和EditsLog合并过程
    jQuery中读取json文件示例代码
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/9380558.html
Copyright © 2011-2022 走看看