[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
 
 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 }
View Code

 

posted @ 2020-06-04 21:20  PYWBKTDA  阅读(152)  评论(0编辑  收藏  举报