//有源汇有上下界最大流
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2005,maxm=100005;
const int inf=0x7f7f7f7f;
struct edge{
int to,next,w,num;
}lst[maxm];int len=0,first[maxn],_first[maxn];
void addedge(int a,int b,int w,int num){
lst[len].num=num;
lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++;
lst[len].num=num;
lst[len].to=a;lst[len].next=first[b];lst[len].w=0;first[b]=len++;
}
int q[maxn],vis[maxn],dis[maxn],T,s,t,head,tail,ss,tt;
bool bfs(){
head=tail=0;vis[s]=++T;q[tail++]=s;
while(head!=tail){
int x=q[head++];
for(int pt=first[x];pt!=-1;pt=lst[pt].next){
if(lst[pt].w&&vis[lst[pt].to]!=T){
vis[lst[pt].to]=T;dis[lst[pt].to]=dis[x]+1;q[tail++]=lst[pt].to;
}
}
}
if(vis[t]==T)memcpy(_first,first,sizeof(first));
return vis[t]==T;
}
int dfs(int x,int lim){
if(x==t)return lim;
int flow=0,a;
for(int pt=_first[x];pt!=-1;pt=lst[pt].next){
_first[x]=pt;
if(lst[pt].w&&dis[lst[pt].to]==dis[x]+1&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))){
lst[pt].w-=a;lst[pt^1].w+=a;flow+=a;
if(flow==lim)return flow;
}
}
return flow;
}
int dinic(){
int ans=0,x;
while(bfs())
while(x=dfs(s,inf))ans+=x;
return ans;
}
int totflow[maxn];
void Add(int a,int b,int lo,int hi,int num){
totflow[a]-=lo;totflow[b]+=lo;
addedge(a,b,hi-lo,num);
}
int low[maxm],ans[maxm];
int n,m,tot;
void bound_flow(){
int sum=0;
for(int i=s;i<=t;++i){
if(totflow[i]<0){
addedge(i,tt,-totflow[i],0);
}else{
sum+=totflow[i];
addedge(ss,i,totflow[i],0);
}
}
addedge(t,s,0x7f7f7f7f,0);
int tmps=s,tmpt=t;
s=ss;t=tt;
if(dinic()==sum){
for(int pt=first[ss];pt!=-1;pt=lst[pt].next){
lst[pt].w=lst[pt^1].w=0;
}
for(int pt=first[tt];pt!=-1;pt=lst[pt].next){
lst[pt].w=lst[pt^1].w=0;
}
int flow0=lst[len-1].w;
lst[len-1].w=lst[len-2].w=0;
s=tmps;t=tmpt;
printf("%d\n",flow0+dinic());
for(int i=1;i<=m;++i){
for(int pt=first[i+n];pt!=-1;pt=lst[pt].next){
if(lst[pt].num!=0){
ans[lst[pt].num]=lst[pt].w+low[lst[pt].num];
}
}
}
for(int i=1;i<=tot;++i)printf("%d\n",ans[i]);
}else{
printf("-1\n");
}
}
void work(){
s=0;t=n+m+1;
ss=n+m+2;tt=n+m+3;
memset(first,-1,sizeof(first));len=0;
memset(totflow,0,sizeof(totflow));
int x,y;
for(int i=1;i<=m;++i){
scanf("%d",&x);
Add(n+i,t,x,inf,0);
}
int l,h;
tot=0;
for(int i=1;i<=n;++i){
scanf("%d%d",&x,&y);
Add(s,i,0,y,0);
for(int j=1;j<=x;++j){
++tot;
scanf("%d%d%d",&y,&l,&h);
Add(i,n+y+1,l,h,tot);low[tot]=l;
}
}
bound_flow();printf("\n");
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF)work();
return 0;
}
另一个写法
//这个好像快一点
#include <bits/stdc++.h>
using namespace std;
const int N = 210, M = 100010, INF = 1000000010;
int n, m, s, t, ss, tt, cnt = 1;
int head[N], in[N], fifo[N], depth[N];
struct edge {
int v, nxt, w;
} vec[M];
void addedge(int u, int v, int w) {
vec[++cnt] = (edge){ v, head[u], w };
head[u] = cnt;
}
void add(int u, int v, int w) {
addedge(u, v, w);
addedge(v, u, 0);
}
void get_read() {
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i = 1; i <= m; ++i) {
int u,v,l,r;
scanf("%d%d%d%d",&u,&v,&l,&r);
in[u] -= l, in[v] += l;
add(u, v, r - l);
}
}
bool bfs(int s, int t) {
memset(depth, 0, sizeof(depth));
int f = 0, r = 1;
fifo[1] = s;
depth[s] = 1;
while (f < r) {
int u = fifo[++f];
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (!depth[v] && vec[i].w > 0) {
depth[v] = depth[u] + 1;
fifo[++r] = v;
}
}
}
return depth[t];
}
int dfs(int u, int exp, int t) {
if (!exp || u == t)return exp;
int flow = 0;
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (depth[v] == depth[u] + 1 && vec[i].w > 0) {
int tmp = dfs(v, min(vec[i].w, exp), t);
exp -= tmp, flow += tmp;
vec[i].w -= tmp, vec[i ^ 1].w += tmp;
if (!exp)
break;
}
}
if (!flow) depth[u] = -1;
return flow;
}
int dicnic(int s, int t) {
int ret = 0;
while (bfs(s, t)) ret += dfs(s, INF, t);
return ret;
}
void get_work() {
ss = n + 1;
tt = n + 2;
for (int i = 1; i <= n; ++i) {
if (in[i] > 0)
add(ss, i, in[i]);
else
add(i, tt, -in[i]);
}
add(t, s, INF);
int ret = 0;
dicnic(ss, tt);
for (int i = head[ss]; i; i = vec[i].nxt) {
if (vec[i].w) {
printf("please go home to sleep");
exit(0);
}
}
head[s] = vec[head[s]].nxt;
head[t] = vec[head[t]].nxt;
printf("%d", vec[cnt].w + dicnic(s, t));
}
int main() {
get_read();
get_work();
return 0;
}