题意不多说了,解题思路详见胡波涛的《最小割模型在信息学竞赛的应用》论文。
复习了一下链式前向星,虽然都是ISAP,但是写起来还是有许多要注意的地方。详细见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#define rep(i,a,b) for (int i=a;i<(b+1);i++)
using namespace std;
const int maxn=60000;
const int maxm=600000;
const int inf=1<<28;
int n,m,cnt,head[maxn],pnt[maxm],nxt[maxm],flow[maxm],pre[maxn],d[maxn],iter[maxn],gap[maxn],s,t;
bool vis[maxn]={false};
void addedge(int u,int v,int f){
pnt[cnt]=v;nxt[cnt]=head[u];flow[cnt]=f;head[u]=cnt++;
pnt[cnt]=u;nxt[cnt]=head[v];flow[cnt]=0;head[v]=cnt++;
}
void spfa(){
memset(d,-1,sizeof d);
memset(vis,false,sizeof vis);
queue<int> q;
q.push(t);
vis[t]=true;
d[t]=0;
while (!q.empty()){
int u=q.front();
q.pop();
for (int i=head[u];i!=-1;i=nxt[i])
if (!vis[pnt[i]]&&flow[i^1]>0){
vis[pnt[i]]=true;
d[pnt[i]]=d[u]+1;
q.push(pnt[i]);
}
}
}
int augement(){
int f=0x3f3f3f3f;
for (int i=pre[t];i!=-1;i=pre[pnt[i]]) f=min(f,flow[i^1]);
for (int i=pre[t];i!=-1;i=pre[pnt[i]]){
flow[i^1]-=f;
flow[i]+=f;
}
return f;
}
int Max_flow(){
int fl=0;
spfa();
memset(gap,0,sizeof gap);
memset(pre,-1,sizeof pre);
rep(i,0,t) iter[i]=head[i];
rep(i,0,t) if (~d[i]) gap[d[i]]++;
int u=0;
while (d[0]<(t+1)){
if (u==t){
fl+=augement();
u=0;
}
bool adv=false;
for (int &i=iter[u];i!=-1;i=nxt[i]) if (flow[i]&&d[u]==d[pnt[i]]+1){
adv=true;
pre[pnt[i]]=i^1;
u=pnt[i];
break;
}
if (!adv){
int m=t+1;
for (int i=head[u];i!=-1;i=nxt[i]) if (flow[i]&&~d[pnt[i]]) m=min(m,d[pnt[i]]);
if (--gap[d[u]]==0) break;
d[u]=m+1;
gap[d[u]]++;
iter[u]=head[u];
if (u!=0) u=pnt[pre[u]];
}
}
return fl;
}
int main(){
while (~scanf("%d%d",&n,&m)){
cnt=0;
memset(pnt,0,sizeof pnt);
memset(nxt,-1,sizeof nxt);
memset(flow,0,sizeof flow);
memset(head,-1,sizeof head);
s=0,t=n+m+1;
rep(i,1,n){
int x;
scanf("%d",&x);
addedge(m+i,t,x);
}
int sum=0;
rep(i,1,m){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(s,i,c);
addedge(i,a+m,inf);
addedge(i,b+m,inf);
sum+=c;
}
printf("%d\n",sum-Max_flow());
}
return 0;
}