这道题长着网络流的数据范围。
最大权闭合子图问题
跑最小割
#include<bits/stdc++.h> #define eho(x) for(int& i=hed[x];~i;i=net[i]) #define Eho(x) for(int i=head[x];~i;i=net[i]) #define N 52607 #define M 3500007 #define NN 1007 #define sight(c) (c<=‘9‘&&c>=‘0‘) #define INF (1<<29) using namespace std; template <class T> inline void read(T &x) { static char c; static int b; for(c=getchar(),b=1;!sight(c);c=getchar())if (c==‘-‘) b=-1; for(x=0; sight(c); c=getchar()) x=(x<<3)+(x<<1)+c-48; x*=b; } struct G { int head[N],net[M],fall[M],cost[M],s,t,tot,d[N],hed[N],cost2[M]; bool in[N]; queue<int> Q; G() {} inline void updata() { memcpy(cost,cost2,sizeof cost); } inline void cpy() { memcpy(cost2,cost,sizeof cost); } inline void clear() { memset(head,-1,sizeof head); memset(net,-1,sizeof net); tot=-1;} inline void add(int x,int y,int c) { fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=c;} inline void adds(int x,int y,int c) { add(x,y,c); add(y,x,0);} inline bool spfa() { memset(d,127,sizeof d); int x; d[s]=1; Q.push(s); in[s]=1; while (!Q.empty()) { x=Q.front(); Q.pop(); Eho(x) if (cost[i]&&d[fall[i]]>d[x]+1) { d[fall[i]]=d[x]+1; if (!in[fall[i]]) { in[fall[i]]=1,Q.push(fall[i]);} } in[x]=0; } return d[t]<INF; } inline int dfs(int x,int F) { if (x==t|| !F) return F; int flow=0,r; eho(x) if (d[x]+1==d[fall[i]]&&((r=dfs(fall[i],min(F,cost[i])))>0)) { cost[i]-=r; cost[i^1]+=r; F-=r; flow+=r; if (!F) break; } return flow; } int dinic(int A,int B) { s=A; t=B; int flow=0; while (spfa()) { memcpy(hed,head,sizeof head); flow+=dfs(s,INF); } return flow; } } G; int n,m,a[NN],cost[NN][NN],id[NN][NN],vis[NN],idw[NN],cnt,S,T; long long sum; int main () { G.clear(); freopen("sushi.in","r",stdin); freopen("sushi.out","w",stdout); read(n); read(m); for (int i=1;i<=n;i++) read(a[i]); for (int i=1;i<=n;i++) for (int j=i;j<=n;j++) read(cost[i][j]); for (int i=1;i<=n;i++) for (int j=i;j<=n;j++) id[i][j]=++cnt; for (int i=1;i<=n;i++) if (!vis[a[i]]) { vis[a[i]]=1; idw[a[i]]=++cnt; } T=cnt+n+1; memset(vis,0,sizeof vis); for (int i=1;i<=n;i++) if (!vis[a[i]]) { vis[a[i]]=1; G.adds(idw[a[i]],T,m*a[i]*a[i]); } for (int i=1;i<=n;i++) { G.adds(cnt+i,idw[a[i]],INF); G.adds(cnt+i,T,a[i]); } for(int i=1;i<=n;i++) for(int j=i;j<=n;j++){ if(cost[i][j]>0){ sum+=cost[i][j]; G.adds(S,id[i][j],cost[i][j]); G.adds(id[i][j],cnt+i,INF); G.adds(id[i][j],cnt+j,INF); } else if(cost[i][j]<0){ G.adds(id[i][j],T,-cost[i][j]); G.adds(id[i][j],cnt+i,INF); G.adds(id[i][j],cnt+j,INF); } if(i^j){ G.adds(id[i][j],id[i+1][j],INF); G.adds(id[i][j],id[i][j-1],INF); } } printf("%lld\n",sum-G.dinic(S,T)); return 0; }