Codeforces434D 网络流

来源:互联网 发布:php 用户权限 编辑:程序博客网 时间:2024/06/06 13:22

思路:
题意:有n<=50个点,每个点有xi有[li, ri]种取值,-100 <= li <= ri <= 100,并且给定m<=100条边,每条边为u,v,d表示xu<=xv+d。

    每个点value fi(x) = ai*x^2 + bi*x + ci。现在求一种合法的方案,使得权值和最大。

思路:先不考虑的xu<=xv + d。那么建图:

   首先考虑到每个点的权值可能为负,并且求最大与最小割相反,    所以先 取反再+oo(一个很大的数),最后再减掉即可    对于每个点,拆成ri-li+1个点,    对于第k个点,node(k, i)表示第k个点值为i对应的标号    值为i-1跟i连一条边<node(k, i-1), node(k, i),  oo - f(k, i)>的边,    S到第一个点连<S, node(k, l[k]), f(k, l[k])>   最后一个点到T连<node(k,r[k]), Inf>   那么很明显n*oo-最小割就是答案。。   但是如果有了限制条件xu<=xv + d,我们怎么把限制条件加到图上呢?   对于一对关系,xu<=xv+d   考虑到点u,如果node(u, i)到node(u,i+1)之间的边在割集里,那么说明xu=i+1   也就是说如果xv<xu-d是非法的,也就是说对于v在xu-d之前出现割是非法的。   那么我们可以连<node(u,i), node(v, i-d), Inf>的边,使得方案合法。。

from http://www.cnblogs.com/yzcstc/p/4062097.html

//By SiriusRen#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 111#define maxn 11111#define M 88888#define inf 0x3f3f3f3fint n,m,a[N],b[N],c[N],l[N],r[N],id[N][N*2],cnt,maxx=-inf,ed=11100;int first[maxn],vis[maxn],v[M],w[M],nxt[M],tot,U,V,D,jy,ans;int func(int x,int y){return a[x]*y*y+b[x]*y+c[x];}void Add(int x,int y,int z){w[tot]=z,v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}bool tell(){    memset(vis,-1,sizeof(vis)),vis[0]=0;    queue<int>q;q.push(0);    while(!q.empty()){        int t=q.front();q.pop();        for(int i=first[t];~i;i=nxt[i])            if(w[i]&&vis[v[i]]==-1)                vis[v[i]]=vis[t]+1,q.push(v[i]);    }    return vis[ed]!=-1;}int zeng(int x,int y){    if(x==ed)return y;    int r=0;    for(int i=first[x];~i&&y>r;i=nxt[i])        if(w[i]&&vis[v[i]]==vis[x]+1){            int t=zeng(v[i],min(w[i],y-r));            w[i]-=t,w[i^1]+=t,r+=t;        }    if(!r)vis[x]=-1;    return r;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]);    for(int i=1;i<=n;i++){        scanf("%d%d",&l[i],&r[i]);        for(int j=l[i];j<=r[i];j++)            maxx=max(maxx,func(i,j));    }    maxx++;    memset(first,-1,sizeof(first));    for(int i=1;i<=n;i++){        for(int j=l[i];j<=r[i]+1;j++)id[i][j+100]=++cnt;        for(int j=l[i];j<=r[i];j++)add(id[i][j+100],id[i][j+101],maxx-func(i,j));        add(0,id[i][l[i]+100],inf),add(id[i][r[i]+101],ed,inf);    }    for(int i=1;i<=m;i++) {        scanf("%d%d%d",&U,&V,&D);        for(int j=l[U];j<=r[U]+1;j++)            if(j-D>=l[V]&&j-D<=r[V]+1)add(id[U][j+100],id[V][j-D+100],inf);    }    while(tell())while(jy=zeng(0,inf))ans+=jy;    printf("%d\n",maxx*n-ans);}

这里写图片描述

0 0