思路:

题意:有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);
}

最新文章

  1. Delphi的面向对象编程基础笔记
  2. PHP For Windows/php-5.6.11-Win32-VC11-x64启动脚本
  3. C# Control 控件DrapDrop不触发的问题
  4. 微信扫描二维码安卓弹出默认浏览器(苹果打开App Store)打开下载链接
  5. 深入MySQL复制(三):半同步复制
  6. js判断手机邮箱格式(正则)
  7. Python与矩阵论——特征值与特征向量
  8. MSMQ消息传递的优先级
  9. Storm集成Kafka的Trident实现
  10. VBA 连接文本的自定义函数(可用于数组公式)
  11. python map对象
  12. js forEach for区别
  13. endl的读法
  14. 简单认识python的数据类型和语法
  15. Android 第三方应用接入微信平台研究情况分享
  16. ThinkPHP - 4 - 学习笔记(2015.4.12)
  17. visualvm监控远程机器上的Java程序
  18. 在struts2中配置自定义拦截器放行多个方法
  19. Poco 编译mysql
  20. 优先队列的使用——Expedition

热门文章

  1. LeetCode -- 求字符串数组中的最长公共前缀
  2. luogu 2679 子串
  3. HttpWebRequest 表单提交
  4. KMP算法中求next数组的实质
  5. github上下载开源项目
  6. ActiveMQ学习笔记(9)----ActiveMQ静态网络连接
  7. 洛谷 P1983 车站分级 拓扑排序
  8. java中的json使用
  9. LCT复习
  10. 关于python return 和 print 的区别