# [LOJ 2146][BZOJ 4873][Shoi2017]寿司餐厅

## 题意

Kiana 最近喜欢到一家非常美味的寿司餐厅用餐。

$$n\le 100,a_i\le 1000,m\in\{0,1\}$$

## 题解

### 参考代码

#include <bits/stdc++.h>

const int MAXN=1e2+10;
const int MAXV=1e4+10;
const int MAXE=1e6+10;
const int INF=0x7FFFFFFF;

struct Edge{
int from;
int to;
int flow;
Edge* rev;
Edge* next;
};
Edge E[MAXE];
Edge* cur[MAXV];
Edge* top=E;

int n;
int m;
int a[MAXN];
bool vis[1010];
int depth[MAXV];
int id[MAXN][MAXN];
int val[MAXN][MAXN];

bool BFS(int,int);
int Dinic(int,int);
int DFS(int,int,int);
void Insert(int,int,int);

int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
int s=0,t=1;
int cnt=1,sum=0;
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
scanf("%d",val[i]+j);
id[i][j]=++cnt;
if(i==j)
val[i][j]-=a[i];
if(val[i][j]>=0){
sum+=val[i][j];
Insert(s,id[i][j],val[i][j]);
}
else
Insert(id[i][j],t,-val[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
Insert(id[i][j],id[i+1][j],INF);
Insert(id[i][j],id[i][j-1],INF);
}
}
for(int i=1;i<=n;i++)
Insert(id[i][i],cnt+a[i],INF);
for(int i=1;i<=n;i++){
if(!vis[a[i]]){
vis[a[i]]=true;
Insert(cnt+a[i],t,m*a[i]*a[i]);
}
}
printf("%d\n",sum-Dinic(s,t));
return 0;
}

int Dinic(int s,int t){
int ans=0;
while(BFS(s,t))
ans+=DFS(s,INF,t);
return ans;
}

bool BFS(int s,int t){
memset(depth,0,sizeof(depth));
std::queue<int> q;
q.push(s);
depth[s]=1;
while(!q.empty()){
s=q.front();
q.pop();
if(i->flow>0&&depth[i->to]==0){
depth[i->to]=depth[s]+1;
if(i->to==t)
return true;
q.push(i->to);
}
}
}
return false;
}

int DFS(int s,int flow,int t){
if(s==t||flow<=0)
return flow;
int rest=flow;
for(Edge*& i=cur[s];i!=NULL;i=i->next){
if(i->flow>0&&depth[i->to]==depth[s]+1){
int tmp=DFS(i->to,std::min(rest,i->flow),t);
if(tmp<=0)
depth[i->to]=0;
rest-=tmp;
i->flow-=tmp;
i->rev->flow+=tmp;
if(rest<=0)
break;
}
}
return flow-rest;
}

inline void Insert(int from,int to,int flow){
top->from=from;
top->to=to;
top->flow=flow;
top->rev=top+1;