给出
n
n
n个三次函数,其中
x
i
x_i
xi为第
i
i
i个函数的自变量,取值为
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri],另还需满足形如
x
a
≤
x
b
+
d
x_ale x_b+d
xa≤xb+d的
m
m
m个限制,求
∑
f
i
(
x
i
)
sum f_i(x_i)
∑fi(xi)的最大值。
n
,
∣
l
i
∣
,
∣
r
i
∣
≤
100
,
m
≤
500
n,|l_i|,|r_i|le 100,mle 500
n,∣li∣,∣ri∣≤100,m≤500
题解
限制特别难处理,一般会考虑建图跑网络流。本题采用的是求最小割。
每个函数从
l
i
l_i
li到
r
i
r_i
ri依次从源点到汇点连一条链,表示
p
(
p
∈
[
l
i
,
r
i
]
)
p(pin[l_i,r_i])
p(p∈[li,ri])的点连出的边权为
−
f
i
(
p
)
-f_i(p)
−fi(p),断一条边表示该函数所取的自变量,则此处限制了自变量的取值。
对每个限制,移项变为
x
b
≥
x
a
−
d
x_bge x_a-d
xb≥xa−d,即每取一个
x
a
x_a
xa,则需保证
x
b
≥
x
a
−
d
x_bge x_a-d
xb≥xa−d,那么从
a
a
a的每个点
x
a
x_a
xa向
b
b
b中表示
x
a
−
d
x_a-d
xa−d的点连边,边权为
i
n
f
inf
inf。其含义为若
a
a
a的自变量为
x
a
x_a
xa,则必须
b
b
b函数
x
a
−
d
x_a-d
xa−d以后取自变量(断一条边)。
为了保证边权为正,给所有边都加上一个大常数
C
C
C,最后答案为最小割减去
n
∗
C
n*C
n∗C再取相反数。
代码
#include<cstdio>#include<cstring>#include<algorithm>usingnamespace std;#define N 110#define M 510#define R 210#define ll long long#define E 100000000int last[N * R], nxt[R *(N + M)*2], to[R *(N + M)*2], len;int cur[N * R], gap[N * R], dis[N * R];int p[N][R], n, m, S, T, tot;
ll ls[R *(N + M)*2];struct{int a, b, c, d, l, r;}a[N];intct(int k,int i){return i * i * i * a[k].a + i * i * a[k].b + i * a[k].c + a[k].d;}voidadd(int x,int y, ll w){
to[++len]= y;
nxt[len]= last[x];
ls[len]= w + E;
last[x]= len;
to[++len]= x;
nxt[len]= last[y];
ls[len]=0;
last[y]= len;}
ll dfs(int k, ll flow){if(k == T)return flow;
ll have =0;for(int i = cur[k]; i; i = nxt[i]){
cur[k]= i;if(dis[to[i]]+1== dis[k]&& ls[i]){
ll now =dfs(to[i],min(flow - have, ls[i]));
have += now;
ls[i]-= now, ls[i ^1]+= now;if(flow == have)return have;}}
cur[k]= last[k];
gap[dis[k]]--;if(!gap[dis[k]]) dis[S]= tot;
gap[++dis[k]]++;return have;}intmain(){int tn;scanf("%d",&tn);while(tn--){int i, j, x, y, d;memset(last,0,sizeof(last));
len =1;scanf("%d%d",&n,&m);
tot =2, S =1, T =2;for(i =1; i <= n; i++){scanf("%d%d%d%d%d%d",&a[i].a,&a[i].b,&a[i].c,&a[i].d,&a[i].l,&a[i].r);add(S, tot +1,1e12);for(j = a[i].l; j < a[i].r; j++){
p[i][j +100]=++tot;add(tot, tot +1,-ct(i, j));}
p[i][a[i].r +100]=++tot;add(tot, T,-ct(i, a[i].r));}for(i =1; i <= m; i++){scanf("%d%d%d",&x,&y,&d);for(j = a[x].l; j <= a[x].r; j++){if(j - d <= a[y].l)continue;if(j - d > a[y].r)add(p[x][j +100], T,1e12);elseadd(p[x][j +100], p[y][j +100- d],1e12);}}memset(gap,0,sizeof(gap));memset(cur,0,sizeof(cur));memset(dis,0,sizeof(dis));
gap[0]= tot;
ll sum =0;while(dis[S]< tot) sum +=dfs(S,1e15);
sum -=(ll)n * E;if(sum >=1e10)puts("mei ji ge");elseprintf("%lld
",-sum);}return0;}