BZOJ4873 [Shoi2017]寿司餐厅

来源:互联网 发布:filezilla中软件怎么下 编辑:程序博客网 时间:2024/04/26 01:06

也是傻逼题,就是想不出来

考虑最大权闭合子图,对于长度大于1的区间,区间[i,j]的前置条件就是[i+1,j],[i,j-1]

对于单点区间[i,i],另其贡献减去a[i],并且前置条件是权值为m*a[i]*a[i]的点

跑最小割就行了

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 11010#define MAXM 1000010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000struct vec{int to;int fro;int v;};vec mp[MAXM];int tai[MAXN],cnt=1;int num[110][110];int v[110][110];int n,m;int a[110];int tot;int s,t;int ans;int q[MAXN],hd,tl;int d[MAXN];inline void be(int x,int y,int z){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;mp[cnt].v=z;}inline void bse(int x,int y,int z){be(x,y,z);be(y,x,0);}bool bfs(){int i,x,y;memset(d,0,sizeof(d));hd=tl=0;q[tl++]=s;d[s]=1;while(hd!=tl){x=q[hd++];for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(!d[y]&&mp[i].v){d[y]=d[x]+1;q[tl++]=y;}}}return d[t];}int dfs(int x,int mx){if(x==t){return mx;}int i,y,tmp;int re=0;for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(d[y]==d[x]+1&&mp[i].v){tmp=dfs(y,min(mx,mp[i].v));mp[i].v-=tmp;mp[i^1].v+=tmp;re+=tmp;mx-=tmp;if(!mx){return re;}}}if(!re){d[x]=0;}return re;}int main(){int i,j,x;scanf("%d%d",&n,&m);for(i=1;i<=n;i++){scanf("%d",&a[i]);}s=1001;t=tot=1002;for(i=1;i<=1000;i++){bse(i,t,m*i*i);}for(i=1;i<=n;i++){for(j=i;j<=n;j++){num[i][j]=++tot;scanf("%d",&v[i][j]);}}for(i=1;i<=n;i++){for(j=i;j<=n;j++){x=v[i][j];if(i==j){x-=a[i];bse(num[i][j],a[i],INF);}if(x>0){ans+=x;bse(s,num[i][j],x);}else{bse(num[i][j],t,-x);}if(i!=j){bse(num[i][j],num[i+1][j],INF);bse(num[i][j],num[i][j-1],INF);}}}while(bfs()){ans-=dfs(s,INF);}printf("%d\n",ans);return 0;}/*3 12 3 25 -10 15-10 1515*/


0 0
原创粉丝点击