乔乔和牛牛去逛超市了,超市里有 n n n 种商品,他们决定买一些商品回家。
但是,第 i i i 种商品一旦被选择,购买的个数就必须是 L i L_i Li 和 R i R_i Ri 之间的整数(含端点)。
某些商品之间有依赖关系,依赖关系有两种:
- 只有第 x x x 种商品被购买了,第 y y y 种商品才可以被购买。
- 只有第 x x x 种商品被购买了,第 y y y 种商品的购买个数才可以恰好是 L i L_i Li 或 R i R_i Ri。
购买一个商品带来的开心程度和这个商品购买的个数有关,若第 i i i 个商品购买了 x i x_i xi 个, x i > 0 x_i> 0 xi>0,则收益为 a i x i 2 + b i x i + c i a_ix_i^2+b_ix_i+c_i aixi2+bixi+ci,否则为 0 0 0。
现在牛牛和乔乔想知道逛超市的最大总开心程度是多少。
输入格式
第一行包含两个整数 n , m n, m n,m,表示商品数量和依赖关系数量。
接下来 n n n 行,每行包含五个整数 L i , R i , a i , b i , c i L_i,R_i,a_i,b_i,c_i Li,Ri,ai,bi,ci,描述一个商品。
接下来 m m m 行,每行包含三个整数 z , x , y z, x, y z,x,y,表示第 x x x 种商品对第 y y y 种商品存在第 z z z 种关系。
输出格式
输出一个整数,表示最大总开心程度。
数据范围
0 ≤ n ≤ 1 0 4 0 \le n \le 10^4 0≤n≤104,
0 ≤ m ≤ 1 0 5 0 \le m \le 10^5 0≤m≤105,
1 ≤ L i ≤ R i ≤ 1 0 4 1 \le L_i \le R_i \le 10^4 1≤Li≤Ri≤104,
− 5 ≤ a i ≤ 5 -5 \le a_i \le 5 −5≤ai≤5,
− 1 0 4 ≤ b i , c i ≤ 1 0 4 -10^4 \le b_i,c_i \le 10^4 −104≤bi,ci≤104,
L i + 1 ≤ R i − 1 L_i+1 \le R_i-1 Li+1≤Ri−1
1 ≤ x , y ≤ n 1 \le x,y \le n 1≤x,y≤n,
1 ≤ z ≤ 2 1 \le z \le 2 1≤z≤2,
对于 20 % 20\% 20% 的数据, n ≤ 10 , R i ≤ 5 n \le 10,R_i \le 5 n≤10,Ri≤5;
对于 40 % 40\% 40% 的数据, n ≤ 10 n \le 10 n≤10;
对于另外 20 % 20\% 20% 的数据,只有第 1 1 1 种依赖关系。
输入样例:
2 2
1 10 -2 3 -5
1 10 2 3 5
2 1 2
1 2 1
输出样例:
231
样例解释
第 1 1 1 种商品购买 1 1 1 个,第 2 2 2 种商品购买 10 10 10 个。
这个题非常恶心:对于我这个只会一些比较初级的算法的小白而言连暴力蒙20分都做不到。。就是只考虑第一种约束情况,也需要用到图论的最大权闭合图 参考代码如下:
cpp
#include<bits/stdc++.h>
using namespace std;
vector<int>edges[20010],ednum[20010];
long long f[400010],cur[20010],depth[20010],v1[20010],v2[20010];
long long n,m,idx=-1,S,T,tot=0;
long long get(long long a,long long b,long long c,long long l,long long r){
if(a==0) return max(b*l+c,b*r+c);
long long i=(-b)/(2*a),k=i+1,j=i-1;
long long res=max(a*l*l+b*l+c,a*r*r+b*r+c);
if(i>=l&&i<=r) res=max(res,a*i*i+b*i+c);
if(k>=l&&k<=r) res=max(res,a*k*k+b*k+c);
if(j>=l&&j<=r) res=max(res,a*j*j+b*j+c);
return res;
}
void add(int a,int b,int c){
edges[a].push_back(b),ednum[a].push_back(++idx),f[idx]=c;
edges[b].push_back(a),ednum[b].push_back(++idx),f[idx]=0;
}
bool bfs(){
memset(depth,-1,sizeof depth);
depth[S]=0,cur[S]=0;
queue<int>nodes;
nodes.push(S);
while(!nodes.empty()){
int temp=nodes.front();
nodes.pop();
for(int i=0;i<edges[temp].size();i++){
int t=edges[temp][i],e=ednum[temp][i];
if(depth[t]!=-1||f[e]==0) continue;
cur[t]=0;
depth[t]=depth[temp]+1;
if(t==T) return true;
nodes.push(t);
}
}
return false;
}
long long dfs(long long now,long long limit){
if(now==T) return limit;
long long flow=0;
for(int i=cur[now];i<edges[now].size()&&flow<limit;i++){
int t=edges[now][i],e=ednum[now][i];
cur[now]=i;
if(depth[t]!=depth[now]+1||f[e]==0) continue;
long long u=dfs(t,min(limit-flow,f[e]));
if(u==0) depth[t]=-1;
flow+=u,f[e]-=u,f[e^1]+=u;
}
return flow;
}
long long dinic(){
long long res=0;
while(bfs()) res+=dfs(S,0x3f3f3f3f3f3f3f3f);
return res;
}
int main(){
cin>>n>>m;
S=0,T=2*n+1;
for(int i=1;i<=n;i++){
int l,r,a,b,c;
cin>>l>>r>>a>>b>>c;
v1[i]=get(a,b,c,l+1,r-1);
v2[i]=get(a,b,c,l,r)-v1[i];
add(i+n,i,0x3f3f3f3f);
}
for(int i=1;i<=n;i++){
if(v1[i]>0) add(S,i,v1[i]),tot+=v1[i];
else if(v1[i]<0) add(i,T,-v1[i]);
if(v2[i]>0) add(S,i+n,v2[i]),tot+=v2[i];
else if(v2[i]<0) add(i+n,T,-v2[i]);
}
for(int i=0;i<m;i++){
int z,x,y;
cin>>z>>x>>y;
if(z==1) add(y,x,0x3f3f3f3f);
else add(y+n,x,0x3f3f3f3f);
}
cout<<tot-dinic();
return 0;
}