题解:
费用流
拆点
代码:
#include<bits/stdc++.h> const int N=40010; using namespace std; int n,m,l=1,fi[N],ne[N],to[N],v[N],c[N],cnt; int x,y,z,q[N*2],dis[N],fa[N],Ans,fl[N],flag[N]; void jb(int x,int y,int V,int C) { to[++l]=y;v[l]=V;c[l]=C;ne[l]=fi[x];fi[x]=l; to[++l]=x;v[l]=0;c[l]=-C;ne[l]=fi[y];fi[y]=l; } bool SPFA() { int head=0,tail=1; memset(fl,0x3f,sizeof fl); memset(flag,0,sizeof flag); memset(dis,0x3f,sizeof dis); q[1]=0;fl[0]=1e9;dis[0]=0; while (head!=tail) { head++; if (head==N) head=0; x=q[head];flag[x]=0; for (int i=fi[x];i;i=ne[i]) { if (dis[to[i]]>dis[x]+c[i]&&v[i]>0) { dis[to[i]]=dis[x]+c[i]; fa[to[i]]=i; fl[to[i]]=min(fl[x],v[i]); if (!flag[to[i]]) { flag[to[i]]=1; tail++; if (tail==N) tail=0; q[tail]=to[i]; } } } } return fl[cnt]<1e9; } void flow() { for (int i=cnt;i;i=to[fa[i]^1]) { v[fa[i]]-=fl[cnt]; v[fa[i]^1]+=fl[cnt]; Ans+=c[fa[i]]*fl[cnt]; } } int main() { scanf("%d%d",&n,&m); cnt=n+n+1; for (int i=1;i<=n;i++)scanf("%d",&x),jb(0,i+n,1,x); for (int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); if (x>y) swap(x,y); jb(x,y+n,1,z); } for (int i=1;i<=n;i++)jb(0,i,1,0),jb(i+n,cnt,1,0); while (SPFA())flow(); printf("%d\n",Ans); }