您的位置:首页 > 其它

BZOJ4873: [Shoi2017]寿司餐厅

2017-06-08 14:16 417 查看
BZOJ4873

。。感觉网络流题目做的也不少了。。可是拿到了还是不会QAQ

一开始把mx2+cx的x看成了取的该种寿司的个数。。。

所求答案是获得的美味度之和减去花费。可以联想到最大权闭合子图。

然后考虑一下依赖关系。

首先可以想到源向每个区间连边,边权为Di,j,这是收益。

在考虑花费,每一种寿司向汇连边,花费应该是mx2+cx,可是这个c并不确定。

那么转化一下。答案=(美味度之和-∑cx)-∑mx2

然后再考虑这个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
,nextedge[M],w[M],cur
;
int Level
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: