Luogu P5331 [SNOI2019]通信

Link
KM

#include<cstdio>
#include<cstring>
#include<algorithm>
using i64=long long;
const int N=2007,inf=0x3f3f3f3f;
int n,a[N],w[N][N],vis[N],A[N],B[N],slack[N],pre[N],mat[N];
int read(){int x;scanf("%d",&x);return x;}
void bfs(int x)
{
    memset(vis+1,0,8*n),memset(pre+1,0,8*n),memset(slack+1,0x3f,8*n),mat[0]=x,x=0;
    do
    {
	int u=mat[x],d=inf,t;vis[x]=1;
	for(int v=1;v<=2*n;++v)
	    if(!vis[v])
	    {
		if(slack[v]>A[u]+B[v]-w[u][v]) slack[v]=A[u]+B[v]-w[u][v],pre[v]=x;
		if(slack[v]<=d) d=slack[v],t=v;
	    }
	for(int v=0;v<=2*n;++v) if(vis[v]) A[mat[v]]-=d,B[v]+=d; else slack[v]-=d;
	x=t;
    }while(mat[x]);
    while(x) mat[x]=mat[pre[x]],x=pre[x];
}
int main()
{
    n=read(),memset(w,-0x3f,sizeof w);int W=read();i64 ans=0;
    for(int i=1;i<=n;++i) a[i]=read(),w[i][i+n]=-W;
    for(int i=1;i<=n;++i) for(int j=1;j<i;++j) w[i][j]=-abs(a[i]-a[j]);
    for(int i=1;i<=n;++i) bfs(i);
    for(int i=1;i<=n*2;++i) if(mat[i]&&mat[i]<=n) ans+=w[mat[i]][i];
    printf("%lld",-ans);
}
上一篇:HDU-5955 Guessing the Dice Roll(AC自动机 + 概率DP + 高斯消元)


下一篇:最小费用最大流