最大权闭合子图。
中转站相当于是负权点,向 \(T\) 连边,流量为 \(P_i\) 。
每条边建一个点 \(x\),连向两个端点 \(A_i,B_i\) ,流量为 \(Inf\) ,并且从 \(S\) 向 \(x\) 连一条流量为 \(C_i\) 的边。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=55010,M=N*6,Inf=0x3f3f3f3f;
int n,m,s,t,ans,cnt=1;
int vr[M],nxt[M],w[M],fir[N],cur[N],d[N];
inline void add(int u,int v,int ww) {
vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,w[cnt]=ww;
vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt,w[cnt]=0;
}
queue<int> q;
inline bool bfs() {
memset(d,0,sizeof d),memcpy(cur,fir,sizeof cur);
d[s]=1,q.push(s); while(q.size()) {
R u=q.front(); q.pop();
for(R i=fir[u];i;i=nxt[i]) if(w[i]) {
R v=vr[i]; if(!d[v]) d[v]=d[u]+1,q.push(v);
}
} return d[t];
}
inline int dfs(int u,int f) {
if(u==t||f<=0) return f; R res=f;
for(R& i=cur[u];i;i=nxt[i]) if(w[i]) {
R v=vr[i]; if(d[v]==d[u]+1) {
R tmp=dfs(v,min(res,w[i]));
if(!tmp) d[v]=0;
res-=tmp,w[i]-=tmp,w[i^1]+=tmp;
if(!res) return f;
}
} return f-res;
}
inline void dinic() {while(bfs()) ans-=dfs(s,Inf);}
inline void main() {
n=g(),m=g(),t=n+m+1;
for(R i=1;i<=n;++i) add(i,t,g());
for(R i=1,u,v,w;i<=m;++i) u=g(),v=g(),ans+=(w=g()),
add(i+n,u,Inf),add(i+n,v,Inf),add(s,i+n,w);
dinic(); printf("%d\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}
2019.12.30
原文:https://www.cnblogs.com/Jackpei/p/12121544.html