Codeforces 434(#248 Div1) D. Nanami's Power Plant

問題

整数x1, x2, ..., xnに対してn個の制約
l[i] ≦ xi ≦ r[i] (1≦i≦n)
および、m個の制約
x[u[i]] ≦ x[v[i]] + d[i] (1≦i≦m)が与えられるとき、
Σa[i] * x[i]^2 + b[i] * x[i] + c[i]を最大化せよ。

制約条件

n≦50, m≦100

ai ≦10, bi ≦1000, ci ≦1000

-100≦l[i]≦r[i]≦100

方針

以下f(i, x) = a[i]*x[i]^2 + b[i]*x[i] + c[i]と書く。


最小カット。
m個の制約がない場合を考える。
各変数ごとに、xi = kに相当する頂点を考えたい。
以後この頂点を(xi, k)とあらわす。


カットで考えたいので、(xi, k)がT側⇔xi≦kを意味するようにする。
すると、xi = kであるときにf(i, k)の得点が入るようにするためには、
(xi, k)と(xi, k - 1)の間を容量f(i, k)の辺でつないで、
切れたときにf(i, k)のカットが増えるようにすればよい。


(実際にはf(i, k)が負になりうるので、f(i, k) + BIGとして、後からBIGを全部引く)
また、xi = l[i]もありうるので、作る頂点は(xi, l[i] - 1)から(xi, r[i])まで。


Sから(xi, l[i] - 1)へは容量無限の辺
(xi, r[i])からTへは容量無限の辺を張る。


m個の制約を実現する方法を考える。
xu≦xv + dなる制約があるということは、
全てのkについてk

ソースコード

int n, m;
int a[50], b[50], c[50];
int l[50], r[50];

int f(int i, int x){
	return a[i] * x * x + b[i] * x + c[i];
}

int main(){
	
	cin >> n >> m;
	
	const ll BIG = 1000000;
	int s = 0, t;
	int base[60] = {};
	
	rep(i, n) cin >> a[i] >> b[i] >> c[i];
	rep(i, n){
		cin >> l[i] >> r[i];
		base[i] = s;
		s += r[i] - l[i] + 2;
	}
	t = s + 1;
	
	flowGraph g(t + 1);
	rep(i, n){
		g.add(s, base[i], inf);
		int k = base[i];
		rep(j, r[i] - l[i] + 1) g.add(k, k + 1, BIG - f(i, l[i] + j)), k++;
		g.add(k, t, inf);
	}
	rep(i, m){
		int u, v, d;
		cin >> u >> v >> d; u--; v--;
		for(int j = l[u] - 1; j <= r[u]; j++){
			
			if(j - d >= l[v] - 1 && j - d <= r[v])
			g.add(j - l[u] + 1 + base[u], j - d - l[v] + 1 + base[v], inf);
		}
	}
	cout << n * BIG - g.max_flow(s, t) << endl;
	
	return 0;
}