Codeforces434D 网络流

思路:
题意:有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 0x3f3f3f3f
int 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);
}

这里写图片描述

posted @ 2017-01-04 10:15  SiriusRen  阅读(151)  评论(0编辑  收藏  举报