链接:https://www.luogu.org/problemnew/show/P4174
题解:
最大权闭合子图裸题
常规连边,砍掉一条边代表不干这件事情
在这题中的体现就是,抉择和顾客间连INF,代表不会被砍
顾客和t连收益,砍了说明没收益
源和花费连边,砍了说明没花费
注意一下数组的大小就可以了,建了8倍的边
代码:
#include <bits/stdc++.h> using namespace std; #define maxn 400010 #define INF 1e9 int n,m,c,dd,e,ans,s,t,d[maxn],head[maxn],l,b[maxn]; bool vis[maxn]; struct re{ int a,b,c,flow; }a[maxn]; void arr(int x,int y,int z,int flow) { a[++l].a=head[x]; a[l].b=y; a[l].c=z; a[l].flow=flow; head[x]=l; } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int> q; q.push(s); d[s]=0; vis[s]=1; while (!q.empty()) { int x=q.front();q.pop(); int u=head[x]; while (u) { int v=a[u].b; if (!vis[v]&&a[u].c>a[u].flow) { vis[v]=1; d[v]=d[x]+1; q.push(v); } u=a[u].a; } } return(vis[t]); } int dfs(int x,int y) { if (x==t||y==0) return y; int flow=0,f,tmp; int u=head[x]; while (u) { int v=a[u].b; if (d[x]+1==d[v]&&(f=dfs(v,min(y,a[u].c-a[u].flow)))>0) { a[u].flow+=f; if (u%2) tmp=u+1; else tmp=u-1; a[tmp].flow-=f; flow+=f; y-=f; if (y==0) break; } u=a[u].a; } return(flow); } int maxflow() { int flow=0; while (bfs()) { flow+=dfs(s,INF); } return(flow); } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); cin>>n>>m; s=0; t=n+m+1; for (int i=1;i<=n;i++) { cin>>b[i]; arr(i+m,t,b[i],0); arr(t,i+m,0,0); } for (int i=1;i<=m;i++) { cin>>c>>dd>>e; arr(i,c+m,INF,0); arr(c+m,i,0,0); arr(i,dd+m,INF,0); arr(dd+m,i,0,0); arr(0,i,e,0); arr(i,0,0,0); ans+=e; } ans-=maxflow(); cout<<ans; }