题解

最大流:得到有源汇上下界可行流后,在删去超级源点,超级汇点,汇点到源点边权为$inf$的边之后,再在残余网络上跑源点到汇点的最大流。
最小流:得到有源汇上下界可行流后,在删去超级源点,超级汇点,汇点到源点边权为$inf$的边之后,再在残余网络上跑汇点到源点的最大流。因为在上下界最小流中,我们需要尽可能缩减残余网络中所有边的权值,需要找残余网络中源点到汇点的最小流,这等价于汇点到源点的最大流。(此时的最小流不为$0$!!因为删点后所有点都不一定满足流入等于流出的限制,所以即使是在最小流中,也可能有边不与源汇相连(流满的边视为不存在)且有流量)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
const int inf = 0x7fffffff;

int Case;
int n,m,S,T,cnt,tot;
int head[N],d[N],ide[N];
ll fin[N],fout[N],we[N];
struct nd{
int ne,to;ll w;
}e[N<<1];

void in(int x,int y,int w){
e[++cnt].to=y;e[cnt].ne=head[x];head[x]=cnt;e[cnt].w=w;
e[++cnt].to=x;e[cnt].ne=head[y];head[y]=cnt;e[cnt].w=0;
}

bool bfs(){
static queue<int>q;
for(int i=1;i<=n+m+4;++i)d[i]=0;
q.push(S);d[S]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].ne){
int y=e[i].to;
if(!d[y]&&e[i].w>0){
d[y]=d[x]+1;
q.push(y);
}
}
}
return d[T]!=0;
}

ll dinic(int x=S,ll mn=inf){
if(x==T||!mn)return mn;
ll flow=0;
for(int i=head[x];i;i=e[i].ne){
int y=e[i].to;
ll maxf;
if(d[y]==d[x]+1&&(maxf=dinic(y,min(mn,e[i].w)))>0){
e[i].w-=maxf;e[i^1].w+=maxf;
mn-=maxf;flow+=maxf;
if(!mn)break;
}
}
if(!flow)d[x]=0;
return flow;
}

void add(int x,int y,int l,int r){
fin[y]+=l;
fout[x]+=l;
in(x,y,r-l);
}

int main(){
while(scanf("%d%d",&n,&m)!=EOF){
S=n+m+1;T=n+m+2;
for(int i=1;i<=n+m+4;++i)head[i]=fin[i]=fout[i]=0;
cnt=1;tot=0;
for(int i=1,val;i<=m;++i){
scanf("%d",&val);
add(S,i,val,inf);
}
for(int i=1,c,d;i<=n;++i){
scanf("%d%d",&c,&d);
add(m+i,T,0,d);
for(int j=1,x,l,r;j<=c;++j){
scanf("%d%d%d",&x,&l,&r);x++;
add(x,m+i,l,r);
++tot;
ide[tot]=cnt;
we[tot]=l;
}
}
S=n+m+3;T=n+m+4;
ll Maxflow=0;
for(int i=1;i<=n+m+2;++i)
if(fin[i]>=fout[i]){
in(S,i,fin[i]-fout[i]);
Maxflow+=fin[i]-fout[i];
}
else in(i,T,fout[i]-fin[i]);
in(n+m+2,n+m+1,inf);
int idrev=cnt;
while(bfs())Maxflow-=dinic();
if(Maxflow!=0)puts("-1");
else{
Maxflow=e[idrev].w;
e[idrev].w=e[idrev^1].to=0;
for(int i=head[S];i;i=e[i].ne){
e[i].w=e[i^1].w=0;
}
for(int i=head[T];i;i=e[i].ne){
e[i].w=e[i^1].w=0;
}
S=n+m+1;T=n+m+2;//swap(S,T);
while(bfs())Maxflow+=dinic();
printf("%d\n",Maxflow);
for(int i=1;i<=tot;++i)printf("%d\n",we[i]+e[ide[i]].w);
}
printf("\n");
}
}