题解:
拆点网络流
然后用总和-最大流
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int N=100005; int ne[N],tot,fi[N],zz[N],z,sl[N],q[N],T,n,m,sum,F[N],dis[N],x,y,cas,ans,f[N]; void jb(int x,int y,int z) { ne[tot]=fi[x]; fi[x]=tot; zz[tot]=y; sl[tot++]=z; ne[tot]=fi[y]; fi[y]=tot; zz[tot]=x; sl[tot++]=0; } int bfs() { memset(dis,0xff,sizeof dis); dis[1]=0; int l=0,r=1; q[1]=1; while (l<r) { int j=q[++l]; for (int i=fi[j];i!=-1;i=ne[i]) if (dis[zz[i]]<0&&sl[i]>0) { dis[zz[i]]=dis[j]+1; q[++r]=zz[i]; } } if (dis[2*n+2]>0)return 1; return 0; } int find(int x,int low) { int b=0; if (x==2*n+2)return low; for (int i=fi[x];i!=-1;i=ne[i]) if (sl[i]>0&&dis[zz[i]]==dis[x]+1&&(b=find(zz[i],min(low,sl[i])))) { sl[i]-=b; sl[i^1]+=b; return b; } return 0; } int main() { scanf("%d%d",&n,&m); memset(fi,-1,sizeof fi); for (int i=1;i<=n;i++) { scanf("%d",&F[i]); jb(1,i+1,F[i]); jb(i+1+n,n*2+2,F[i]); sum+=F[i]; } while (m--) { scanf("%d%d%d",&x,&y,&z); jb(x+1,1+n+y,z); } int t; while (bfs()) while (t=find(1,1e9))ans+=t; printf("%d\n",sum-ans); }