题面
短神当时在考场上一眼把这个题秒了,然后吐槽说THU是不是都喜欢把最水的放在第三道=。=???
不愧是大爷orz
可以看出来是最大权闭合子图,问题是怎么建边(废话)
把每个区间看成一个点,每种寿司看成一个点
1.首先是最大权闭合子图的标准连法,对区间连,不说了
2.区间具有包含关系,所以$(i,j)(i!=j)$向$(i+1,j)$和$(i,j-1)$连边,流量为无穷大
3.每种寿司向汇点连$mx^2$的边
4.每个寿司(即$(i,i)$这种区间)向对应的寿司种类连边
5.每个寿司向汇点连x的边
注意就是网络流求最小割的时候和式要拆开连,连成一条链就成了取最小的一项了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int B=110,N=12000,M=32000,inf=1e9; 6 int p[N],noww[2*M],goal[2*M],flow[2*M]; 7 int num[B],val[B][B],idx[B][B],lnk[N]; 8 int pp[N],dep[N],que[N]; 9 int n,m,s,t,f,b,cnt,tot,ans; 10 void Link(int f,int t,int v) 11 { 12 noww[++cnt]=p[f],p[f]=cnt; 13 goal[cnt]=t,flow[cnt]=v; 14 noww[++cnt]=p[t],p[t]=cnt; 15 goal[cnt]=f,flow[cnt]=0; 16 } 17 void Init(int st,int ed) 18 { 19 for(int i=1;i<=ed;i++) pp[i]=p[i]; 20 memset(dep,-1,sizeof dep); 21 que[f=b=0]=st,dep[st]=0; 22 } 23 bool Layering(int st,int ed) 24 { 25 Init(st,ed); 26 while(f<=b) 27 { 28 int tn=que[f++]; 29 for(int i=pp[tn];i;i=noww[i]) 30 if(flow[i]&&dep[goal[i]]==-1) 31 dep[goal[i]]=dep[tn]+1,que[++b]=goal[i]; 32 } 33 return ~dep[ed]; 34 } 35 int Augmenting(int nd,int ed,int mn) 36 { 37 if(nd==ed||!mn) 38 return mn; 39 int tmp,tep=0; 40 for(int i=pp[nd];i;i=noww[i]) 41 { 42 pp[nd]=i; 43 if(dep[goal[i]]==dep[nd]+1) 44 if(tmp=Augmenting(goal[i],ed,min(mn,flow[i]))) 45 { 46 flow[i]-=tmp,mn-=tmp; 47 flow[i^1]+=tmp,tep+=tmp; 48 if(!mn) break; 49 } 50 } 51 return tep; 52 } 53 void Dinic_Maxflow(int st,int ed) 54 { 55 while(Layering(st,ed)) 56 ans-=Augmenting(st,ed,inf); 57 } 58 int main() 59 { 60 scanf("%d%d",&n,&m); 61 for(int i=1;i<=n;i++) 62 scanf("%d",&num[i]); 63 for(int i=1;i<=n;i++) 64 for(int j=i;j<=n;j++) 65 scanf("%d",&val[i][j]),idx[i][j]=++tot; 66 s=n*(n+1)/2+1001,t=s+1,cnt=1; 67 for(int i=1;i<=n;i++) 68 for(int j=i;j<=n;j++) 69 { 70 if(i!=j) 71 { 72 Link(idx[i][j],idx[i+1][j],inf); 73 Link(idx[i][j],idx[i][j-1],inf); 74 } 75 if(val[i][j]<0) Link(idx[i][j],t,-val[i][j]); 76 else Link(s,idx[i][j],val[i][j]),ans+=val[i][j]; 77 } 78 for(int i=1;i<=n;i++) 79 { 80 Link(idx[i][i],t,num[i]),Link(idx[i][i],tot+num[i],inf); 81 if(!lnk[num[i]]) Link(tot+num[i],t,m*num[i]*num[i]),lnk[num[i]]=true; 82 } 83 Dinic_Maxflow(s,t),printf("%d",ans); 84 return 0; 85 }