#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int inf=1e9;
int n,m,ss,tt,s,t,s_,ans;
struct edge{
int to,nxt,w,flow;
}d[maxn]; int head[maxn],cnt=1;
int in[maxn],dis[maxn],flow[maxn],pre[maxn],vis[maxn];
void add(int u,int v,int w,int flow){
d[++cnt]=(edge){v,head[u],w,flow},head[u]=cnt;
d[++cnt]=(edge){u,head[v],-w,0},head[v]=cnt;
}
void ins(int u,int v,int l,int r,int w){
add(u,v,w,r-l);//上界-下界才是流量
in[u]-=l,in[v]+=l;//u需要流入l,y需要流出l
ans+=l*w;
}
bool spfa(int s,int t)
{
for(int i=0;i<=tt*2;i++) dis[i]=inf;
queue<int>q; q.push(ss);
dis[s]=0,flow[s]=inf;
while( !q.empty() )
{
int u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( !d[i].flow||dis[v]<=dis[u]+d[i].w ) continue;
dis[v]=dis[u]+d[i].w;
pre[v]=i; flow[v]=min( flow[u],d[i].flow );
if( !vis[v] ) q.push( v ),vis[v]=1;
}
}
return dis[t]!=inf;
}
int dinic(int s,int t)
{
int ans=0,i;
while( spfa(s,t) )
{
ans+=flow[t]*dis[t];
int x=t;
while( x!=s )
{
i=pre[x];
d[i].flow-=flow[t],d[i^1].flow+=flow[t];
x=d[i^1].to;
}
}
return ans;
}
int main()
{
cin >> n >> m;
s=n*2+1,t=s+1;
ss=t+1,tt=ss+1;
int ans=0;
for(int i=1;i<=n;i++)
{
int x; cin >> x;
ins(s,i,0,1,x);//瞬间移动,下界0次,上界1次
ins(i+n,t,0,1,0);
ins(i,i+n,1,1,0);
}
for(int i=1;i<=m;i++)
{
int l,r,w;
cin >> l >> r >> w;
if( l>r ) swap(l,r);
ins(l+n,r,0,1,w);
}
for(int i=1;i<=t;i++)
{
if( in[i]>0 ) add(ss,i,0,in[i]);
else add(i,tt,0,-in[i]);
}
add(t,s,0,inf);
cout << ans+dinic(ss,tt);
}
上下界最小可行费用流[模板]
猜你喜欢
转载自blog.csdn.net/jziwjxjd/article/details/108304040
今日推荐
周排行