添加超级源和超级汇,然后将s和正权边相连,负权边和t相连,这时候对应的每一个割对应着一种方案,然后最小割即可
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) #define efo(i,x) for(int i=last[x];i!=0;i=e[i].next) using namespace std; inline LL read() { LL d=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } #define N 6005 #define M 50005 #define inf 0x7fffffff struct edge { int y,f,next; }e[M*10]; int last[N*10],ne=1; int h[N*10]; int n,m; void add(int x,int y,int w) { e[++ne].y=y;e[ne].f=w;e[ne].next=last[x];last[x]=ne; } void add2(int u,int v,int w) { add(u,v,w);add(v,u,0); } int q[N*10]; bool bfs(int s,int t) { memset(h,0,sizeof(h)); int head=0,tt=1; q[1]=s;h[s]=1; while(head<tt) { int now=q[++head]; if(now==t)return 1; efo(i,now) if(h[e[i].y]==0&&e[i].f) { // cout<<e[i].y<<' '<<e[i].f<<endl; q[++tt]=e[i].y; h[e[i].y]=h[now]+1; } } return 0; } int dfs(int x,int maxf,int t) { // cout<<x<<' '<<maxf<<' '<<t<<endl; if(x==t) return maxf; int ret=0,f=0; efo(i,x) if(e[i].f!=0&&h[e[i].y]==h[x]+1) { f=dfs(e[i].y,min(maxf-ret,e[i].f),t); // cout<<e[i].y<<' '<<f<<endl; e[i].f-=f; e[i^1].f+=f; ret+=f; if(ret==maxf)return ret; } return ret; } int dinic(int s,int t) { int ans=0; // cout<<"begin"<<endl; while(bfs(s,t))ans+=dfs(s,inf,t); return ans; } int main() { n=read(),m=read(); fo(i,1,n) { int x=read(); add2(0,i,x); } int sum=0; fo(i,1,m) { int x=read(),y=read(),w=read(); add2(x,n+i,inf); add2(y,n+i,inf); add2(n+i,n+m+1,w); sum+=w; } int ans=dinic(0,n+m+1); cout<<sum-ans<<endl; return 0; }