题意:有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>的边,使得方案合法。。

code:

 #include <bits/stdc++.h>
using namespace std;
#define M0(a) memset(a, 0, sizeof(a))
#define Inf 0x3fffffff
const int maxn = ;
const int maxm = ;
const int big = ;
struct oo{
int y, f, next;
};
struct MaxFlow{
int n, S, T, tot;
int son[maxn], dist[maxn], gap[maxn];
oo e[maxm];
int sap(int x, int aug){
if (x == T) return aug;
int mind = n;
int sum = , f;
for (int p = son[x]; p != -; p = e[p].next){
int y = e[p].y;
if (dist[y] + == dist[x] && e[p].f){
f = sap(y, min(e[p].f, aug - sum));
e[p].f -= f;
e[p^].f += f;
sum += f;
if (sum == aug || dist[S] >= n) return sum;
}
if (e[p].f) mind = min(mind, dist[y]);
}
if (!sum){
if (!(--gap[dist[x]])) dist[S] = n;
++gap[dist[x] = mind + ];
}
return sum;
}
void add(int x, int y, int f){
e[tot].y = y; e[tot].f = f;
e[tot].next = son[x]; son[x] = tot++;
e[tot].y = x; e[tot].f = ;
e[tot].next = son[y]; son[y] = tot++;
} void init(int S, int T, int n){
memset(son, -, sizeof(son));
tot = ;
this->S = S, this->T = T, this->n = n;
}
int maxflow(){
M0(gap);
M0(dist);
gap[] = n;
int ans = ;
while (dist[S] < n) ans += sap(S, Inf);
return ans;
}
} F;
int S, T;
int n, m, a[], b[], c[], l[], r[];
inline int f(const int&k, const int& x){
return big - (a[k] * x * x + b[k] * x + c[k]);
} inline int node(const int&k, const int& x){
return x == l[k] - ? S : (k-) * + x + ;
} void solve(){
for (int i = ; i <= n; ++i) scanf("%d%d%d", &a[i], &b[i], &c[i]);
for (int i = ; i<= n; ++i) scanf("%d%d", &l[i], &r[i]);
S = , T = * n + ;
F.init(S, T, T + );
for (int i = ; i <= n; ++i){
for (int j = l[i]; j <= r[i]; ++j)
F.add(node(i, j-), node(i, j), f(i, j));
F.add(node(i, r[i]), T, Inf);
}
int u, v, d;
int x;
for (int i = ; i <= m; ++i){
scanf("%d%d%d", &u, &v, &d);
for (int j = l[v]; j <= r[v]; ++j) if (j + d <= r[u]){
x = j + d;
if (x < l[u]) x = l[u] -;
F.add(node(u, x), node(v, j), Inf);
}
}
int ans = big * n;
ans -= F.maxflow();
cout << ans << endl;
} int main(){
// freopen("a.in", "r", stdin);
while (scanf("%d%d", &n, &m) != EOF){
solve();
}
}
05-11 20:24