[bzoj4873]寿司餐厅
首先注意题目中的一些细节问题:1.同一个区间不能累加;2.每一种寿司才能提供$x$的代价;3.每一种代号的寿司才能贡献$mx^{2}$的代价
这些就很好的为最小割提供了条件,考虑最大权闭合子图的建图:
1.$(S,id(i,j),d[i][j])(d[i][j]\ge 0)$,$(id(i,j),T,-d[i][j])(d[i][j]<0)$,先将所有大于等于0的累加起来,然后将不选的切掉
2.$(id(i,j),id(i,j-1),oo)$,$(id(i,j),id(i-1,j),oo)$,$(id(i,i),id(i),oo)$,表示选这个就要选子区间(不能直接将子区间的收益加到上面,因为细节1)
3.$(id(i),T,type(id(i)))$,$(type(i),T,mi^{2})$,$(id(i),type(id(i)),oo)$,这些都只需要删掉一次就可以无限选,因为细节2和3
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 20005 4 #define oo 0x3f3f3f3f 5 struct ji{ 6 int nex,to,len; 7 }edge[N<<2]; 8 queue<int>q; 9 int E,n,m,x,ans,head[N],a[N],vis[N],d[N],work[N]; 10 int id(int x,int y){ 11 return (x-1)*n+y; 12 } 13 void add(int x,int y,int z){ 14 edge[E].nex=head[x]; 15 edge[E].to=y; 16 edge[E].len=z; 17 head[x]=E++; 18 if (E&1)add(y,x,0); 19 } 20 bool bfs(){ 21 q.push(0); 22 memset(vis,0,sizeof(vis)); 23 memset(d,0,sizeof(d)); 24 vis[0]=1; 25 while (!q.empty()){ 26 int k=q.front(); 27 q.pop(); 28 for(int i=head[k];i!=-1;i=edge[i].nex) 29 if ((edge[i].len)&&(!vis[edge[i].to])){ 30 vis[edge[i].to]=1; 31 q.push(edge[i].to); 32 d[edge[i].to]=d[k]+1; 33 } 34 } 35 return d[N-5]>0; 36 } 37 int dfs(int k,int s){ 38 if (k==N-5)return s; 39 for(int &i=work[k];i!=-1;i=edge[i].nex) 40 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){ 41 int p=dfs(edge[i].to,min(s,edge[i].len)); 42 if (p){ 43 edge[i].len-=p; 44 edge[i^1].len+=p; 45 return p; 46 } 47 } 48 return 0; 49 } 50 int main(){ 51 scanf("%d%d",&n,&m); 52 memset(head,-1,sizeof(head)); 53 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 54 for(int i=1;i<=n;i++) 55 for(int j=i;j<=n;j++){ 56 scanf("%d",&x); 57 if (x<0)add(id(i,j),N-5,-x); 58 else{ 59 ans+=x; 60 add(0,id(i,j),x); 61 } 62 if (i<n)add(id(i,j),id(i+1,j),oo); 63 if (j>1)add(id(i,j),id(i,j-1),oo); 64 } 65 for(int i=1;i<=n;i++){ 66 add(id(i,i),id(n,n)+i,oo); 67 add(id(n,n)+i,id(n,n)+n+a[i],oo); 68 add(id(n,n)+i,N-5,a[i]); 69 } 70 for(int i=1;i<=1000;i++)add(id(n,n)+n+i,N-5,i*i*m); 71 while (bfs()){ 72 memcpy(work,head,sizeof(work)); 73 while (x=dfs(0,oo))ans-=x; 74 } 75 printf("%d",ans); 76 }