 /**//*
Amber《最小割》
题意:n个中转站,每个站建立花费Xi m个客户,每个客户需要中转站Ai,Bi,获得收益为Ci
问最大收益
要满足客户i,必须有中转站Ai,Bi(前提),就是一个闭合图了!
每个客户i作为一个节点分别向相应中转站Ai,Bi连有向边,容量INF
源点s向每个客户连边,容量为收益Ci
每个中转站向汇点t连有向边,容量为建站花费Xi

那么答案就是 总收益-最小割(割边总和)
用户群与必要的中转站是一个闭合图,问题就是选与不选了

选的话,就是S集合了,不选就是T集合了
s到T集合、S集合到t都是割边
选,则需要建站花费,即S集合到t的边
不选,则损失利益,即s到T集合的边
要使最大,肯定是割边和最小,就是最小割了
*/
#include<cstdio>
#include<cstring>

const int MAXN = 55010;
const int INF = 1000000000;

 inline int min(int a,int b) {return a<b?a:b;}

struct Edge
  {
int v,cap;
Edge *next,*pair;
}edge[MAXN*10];

struct Graph
  {
Edge *E[MAXN],*cur[MAXN];
Edge *pE;
int dist[MAXN],num[MAXN];
int n,s,t;
bool found;
void init(int nn,int ss,int tt)
 {
n=nn;
s=ss;
t=tt;
memset(E,0,sizeof(Edge*)*n);
pE=edge;
}
void add(int u,int v,int cap,Edge *pair)
 {
pE->v=v;
pE->cap=cap;
pE->pair=pair;
pE->next=E[u];
E[u]=pE++;
}
void add(int u,int v,int cap)
 {
add(u,v,cap,pE+1);
add(v,u,0,pE-1);
}
int aug(int u,int preCap)
 {
if(u==t)
 {
found=true;
return preCap;
}
int leftCap=preCap;
for(Edge *&it=cur[u];it;it=it->next)
 {
if(it->cap&&dist[u]==dist[it->v]+1)
 {
int d=aug(it->v,min(it->cap,leftCap));
leftCap-=d;
it->cap-=d;
it->pair->cap+=d;
if(dist[s]==n||leftCap==0)return preCap-leftCap;
if(found)break;
}
}
if(!found)//没有dist[v]+1=dist[u]时才调整
 {
int minD=n;
for(Edge *it=E[u];it;it=it->next)
 {
if(it->cap)minD=min(minD,dist[it->v]+1);
}
if(--num[dist[u]]==0)dist[s]=n;
else num[dist[u]=minD]++;
cur[u]=E[u];
}
return preCap-leftCap;
}
int sap()
 {
memset(dist,0,sizeof(int)*n);
memset(num,0,sizeof(int)*n);
memmove(cur,E,sizeof(Edge*)*n);
num[0]=n;
int flow=0;
while(dist[s]<n)
 {
found=false;
flow+=aug(s,INF);
}
return flow;
}
}graph;

int main()
  {
//freopen("in","r",stdin);
//freopen("out","w",stdout);
int n,m,T;
scanf("%d",&T);
while(T--)
 {
scanf("%d%d",&n,&m);
int s=0,t=n+m+1;
graph.init(n+m+2,s,t);
for(int i=1,x;i<=n;i++)
 {
scanf("%d",&x);
graph.add(m+i,t,x);
}
int ans=0;
for(int i=1;i<=m;i++)
 {
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ans+=c;
graph.add(s,i,c);
graph.add(i,m+a,INF);
graph.add(i,m+b,INF);
}
printf("%d\n",ans-graph.sap());
}
return 0;
}

|