[CF434D]Nanami's Power Plant

[CF434D]Nanami's Power Plant

题目大意:

\(N\)个二次函数\(f_i(x)=a_ix^2+b_ix+c_i(l_i\le x\le r_i)\)\(M\)个约束条件\((u,v,d)\),表示\(x_u\le x_v+d\)。请最大化\(\sum_{i=1}^nf_i(x_i)\),其中\(x_i\)是整数。

对于\(100\%\)的数据,\(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 \neq v , |d| \leq 200\),保证所有数均为整数。

思路:

将每个二次函数\(i\)拆成\(node(i,l_i-1)\sim node(i,r_i)\)\(r_i-l_i+2\)个点。

对于所有的\(node(i,l_i-1)\),连边\(s\to node(i,l_i-1)\),容量为\(\infty\)

对于所有的\(node(i,r_i)\),连边\(s\to node(i,r_i)\),容量为\(\infty\)

\(lim\)表示一个足够大的数,对于每个二次函数\(i\)中所有的\(node(i,j)\),连边\(node(i,j-1)\to node(i,j)\),容量为\(lim-f_i(j)\)

考虑约束条件\((u,v,d)\),连边\(node(u,j)\to node(v,j−d)\),容量为\(\infty\)

答案即为\(lim\times n-maxflow\)

源代码:

#include<map>
#include<queue>
#include<cstdio>
#include<cctype>
#include<climits>
#include<cstring>
inline int getint() {
    register char ch;
    register bool neg=false;
    while(!isdigit(ch=getchar())) neg|=ch=='-';
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return neg?-x:x;
}
const int N=51,V=1e4+1,E=1e5+1;
struct Edge {
    int from,to,remain,next;
};
Edge e[E];
int h[V],sz,cnt;
inline void add_edge(const int &u,const int &v,const int &w) {
    e[sz]=(Edge){u,v,w,h[u]};h[u]=sz++;
    e[sz]=(Edge){v,u,0,h[v]};h[v]=sz++;
}
struct Func {
    int a,b,c;
    int operator () (const int &x) const {
        return a*x*x+b*x+c;
    }
};
Func f[N];
int l[N],r[N];
int lev[V],s,t,cur[V];
inline void bfs() {
    memset(lev,-1,sizeof lev);
    lev[s]=0;
    std::queue<int> q;
    q.push(s);
    while(!q.empty()) {
        const int &x=q.front();
        for(register int i=h[x];~i;i=e[i].next) {
            const int &y=e[i].to,&r=e[i].remain;
            if(r&&!~lev[y]) {
                lev[y]=lev[x]+1;
                q.push(y);
            }
        }
        q.pop();
    }
}
int dfs(const int &x,const int &flow) {
    if(x==t) return flow;
    for(int &i=cur[x];~i;i=e[i].next) {
        const int &y=e[i].to;
        if(e[i].remain&&lev[y]>lev[x]) {
            if(int d=dfs(y,std::min(flow,e[i].remain))) {
                e[i].remain-=d;
                e[i^1].remain+=d;
                return d;
            }
        }
    }
    return 0;
}
inline int dinic() {
    int maxflow=0;
    for(;;) {
        bfs();
        if(!~lev[t]) break;
        memcpy(cur,h,sizeof h);
        while(int flow=dfs(s,INT_MAX)) {
            maxflow+=flow;
        }
    }
    return maxflow;
}
std::map<int,int> node[N];
int main() {
    memset(h,-1,sizeof h);
    const int n=getint(),m=getint();
    for(register int i=1;i<=n;i++) {
        const int a=getint(),b=getint(),c=getint();
        f[i]=(Func){a,b,c};
    }cnt=1;
    s=cnt++;
    for(register int i=1;i<=n;i++) {
        l[i]=getint(),r[i]=getint();
        for(register int j=l[i]-1;j<=r[i];j++) {
            node[i][j]=cnt++;
        }
    }
    const int M=INT_MAX/n;
    for(register int i=1;i<=n;i++) {
        add_edge(s,node[i][l[i]-1],INT_MAX);
        for(register int j=l[i];j<=r[i];j++) {
            add_edge(node[i][j-1],node[i][j],M-f[i](j));
        }
        add_edge(node[i][r[i]],t,INT_MAX);
    }
    for(register int i=0;i<m;i++) {
        const int u=getint(),v=getint(),d=getint();
        for(register int j=std::max(l[u],l[v]+d)-1;j<=std::min(r[u],r[v]+d);j++) {
            add_edge(node[u][j],node[v][j-d],INT_MAX);
        }
    }
    printf("%d\n",M*n-dinic());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/skylee03/p/9368191.html