luogu P5192 Zoj3229 Shoot the Bullet|东方文花帖|【模板】有源汇上下界最大流
题面传送门
说是模板却有一点建模难度。
关于有源汇上下界最大流可以看这篇博客这里只说怎么建边。
首先肯定是从源点向每一天连\([0,D_i]\)的边。从每个少女向汇点连\([G_i,INF]\)的边。
然后由每一天向对应的右部点连\([L_i,R_i]\)的边。然后跑网络流即可。时间复杂度\(O(能过)\)
code:
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db long double
#define N 2000
#define eps (1e-14)
#define mod 998244353
using namespace std;
int n,m,st,t,S,T,d[N+5],nows[N+5],in[N+5],x,y,z,l,r,now ,tot;
struct yyy{int to,w,z;}tmp;
struct ljb{
int head,h[N+5];yyy f[N+5<<6];
I void add(int x,int y,int z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}
}s;queue<int> q;
I void get(int x,int y,int z){s.add(x,y,z);s.add(y,x,0);}
I int bfs(){
memset(d,0x3f,sizeof(d));memset(nows,-1,sizeof(nows));while(!q.empty()) q.pop();q.push(S);d[S]=0;nows[S]=s.h[S];
while(!q.empty()){
now=q.front();q.pop();for(int i=s.h[now];~i;i=tmp.z){
tmp=s.f[i];if(!tmp.w||d[tmp.to]<1e9) continue;d[tmp.to]=d[now]+1;
nows[tmp.to]=s.h[tmp.to];q.push(tmp.to);if(tmp.to==T) return 1;
}
}
return 0;
}
I int dfs(int x,int sum){
if(x==T) return sum;yyy tmp;int k,pus=0,i;for(i=nows[x];~i;i=tmp.z){
tmp=s.f[i];nows[x]=i;if(d[tmp.to]!=d[x]+1||!tmp.w) continue;k=dfs(tmp.to,min(tmp.w,sum));
if(!k) d[tmp.to]=1e9;s.f[i].w-=k;s.f[i^1].w+=k;sum-=k;pus+=k;if(!sum) break;
}
return pus;
}
int main(){
freopen("1.in","r",stdin);
re int i;while(~scanf("%d%d",&n,&m)){
s.head=0;st=0;t=n+m+1;S=n+m+2;T=n+m+3;memset(s.h,-1,sizeof(s.h));memset(in,0,sizeof(in));get(t,st,1e9);tot=0;
for(i=1;i<=m;i++) scanf("%d",&x),get(i+n,t,1e9),in[t]+=x,in[i+n]-=x;
for(i=1;i<=n;i++){
scanf("%d%d",&x,&y);get(st,i,y);while(x--) scanf("%d%d%d",&z,&l,&r),z++,get(i,z+n,r-l),in[i]-=l,in[z+n]+=l;
}
for(i=st;i<=t;i++) in[i]>0?(tot+=in[i],get(S,i,in[i])):get(i,T,-in[i]);while(bfs()) tot-=dfs(S,1e9);
if(tot) {printf("-1\n\n");continue;}S=st;T=t;while(bfs()) tot+=dfs(S,1e9);printf("%d\n\n",tot);
}
}