。。感觉网络流题目做的也不少了。。可是拿到了还是不会
QAQ
一开始把
mx2+cx
的
x
看成了取的该种寿司的个数。。。
所求答案是获得的美味度之和减去花费。可以联想到最大权闭合子图。
然后考虑一下依赖关系。
首先可以想到源向每个区间连边,边权为
在考虑花费,每一种寿司向汇连边,花费应该是
mx2+cx
,可是这个
c
并不确定。
那么转化一下。答案=(美味度之和-
然后再考虑这个
cx
减再哪里。显然应减在单个寿司的收益中,对于
a[i]=x
,
D[i][i]−=x
i!=j
时选了
Di,j
就一定会选
Di+1,j
和
Di,j−1
那么区间
i,j
;向
i+1,j
和
i,j−1
连边,边权为
INF
ans=正权和−最小割
【代码】
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define N 100005
#define M 600005
#define Mod 20170408
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ull base=31;
ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,cnt=1,S,T,num,ans,k;
int b[M],p[N],nextedge[M],w[M],cur[N];
int Level[N],D[105][105],A[105],id[105][105];
void Add(int x,int y,int z){
cnt++;
b[cnt]=y;
nextedge[cnt]=p[x];
p[x]=cnt;
w[cnt]=z;
}
void Anode(int x,int y,int z){
Add(x,y,z);Add(y,x,0);
}
bool Bfs()
{
for(int i=S;i<=T;i++) Level[i]=0;
Level[0]=1;
queue<int>q;
q.push(0);
while(!q.empty())
{
int k=q.front();q.pop();
for(int i=p[k];i;i=nextedge[i])
{
int v=b[i];
if(!Level[v]&&w[i])
{
Level[v]=Level[k]+1;
q.push(v);
}
}
}
return Level[T];
}
int Dfs(int x,int maxf)
{
if(x==T||!maxf) return maxf;
int rtn=0;
for(int i=cur[x];i;i=nextedge[i])
{
int v=b[i],f=w[i];
if(Level[v]==Level[x]+1&&f)
{
f=Dfs(v,min(maxf-rtn,f));
w[i]-=f;w[i^1]+=f;
rtn+=f;if(w[i]) cur[x]=i;
}
}
if(!rtn) Level[x]=0;
return rtn;
}
int Dinic()
{
int rtn=0;
while(Bfs())
{
for(int i=0;i<=T;i++) cur[i]=p[i];
rtn+=Dfs(0,INF);
}
return rtn;
}
void Input_Init()
{
n=read(),m=read();
for(int i=1;i<=n;i++) A[i]=read(),k=max(k,A[i]);
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) D[i][j]=read(),id[i][j]=++num;
}
void Build_Graph()
{
T=num+k+1;
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
int x=id[i][j],y;D[i][j]=D[i][j]-((i==j)?A[i]:0);
if(D[i][j]>0) ans+=D[i][j],Anode(0,x,D[i][j]);
else Anode(x,T,-D[i][j]);
if(i==j) {
Anode(x,num+A[i],INF);
continue;
}
y=id[i+1][j];Anode(x,y,INF);
y=id[i][j-1];Anode(x,y,INF);
}
}
for(int i=1;i<=k;i++) Anode(num+i,T,m*i*i);
}
int main()
{
Input_Init();
Build_Graph();
printf("%d\n",ans-Dinic());
return 0;
}