/* 题目大意:某人n天给m个美女拍照 每个美女都有一个最低要求 每天有一个照片数量上限 先给出n m 每个美女的下限 n个{ 第i天拍照的美女数 这天的照片数量上限 依次是 美女编号 这天的下限 上限 } 有源汇 有上下界 最大流 先对 附加 源汇ss tt求依次最大流 若有可行流 再对s t求最大流 这是第二次写这个题,第一次写的挺不顺利 (可能是构图的时候出问题了,不是超时就是错,求最大流的方法就换了三种:sap递归,sap非递归,dinic 我都怀疑我的最大流模版是不是有漏洞,下面的递归sap就是最初用的,当时我还以为这个有问题, 其实,还真有一个问题,下面有,但是该了还是超时,今天看来,是构图的问题) 下面的 非递归sap跑了330ms 递归sap跑了270ms 看来我的模版速度还是不错的 */ #include<stdio.h> #include<string.h> #define inf 0x7fffffff struct edge//边 { int u,v,f,next,b,c;//边的 前节点 后节点 可用流 下条边的编号 原来边上流的上下界 }e[400000]; int head[1400],in[1400],out[1400],n,m,s,t,ss,tt,yong,indexx[400000],ind,sum; /* head 链表头 in 某点的 流入下界和 - 流出下界和 out没用到 yong 指向下一个未用的边 indexx 存储某个美女某天的边的编号index在string.h里边有所以改成这个了 ind 表示下一个未用的 indexx sum 流入tt的流量和 判断有无可行解用 */ void ini()//初始化 { memset(head,-1,sizeof(head)); yong=0; memset(in,0,sizeof(in)); s=m+n,t=s+1,ss=t+1,tt=ss+1; ind=0; sum=0; } void adde(int from,int to,int xia,int shang)//加边 {//加边 e[yong].u=from,e[yong].v=to,e[yong].f=shang-xia,e[yong].b=xia,e[yong].c=shang; e[yong].next=head[from],head[from]=yong++; //同时加它的退边 e[yong].u=to,e[yong].v=from,e[yong].f=0,e[yong].b=xia,e[yong].c=shang; e[yong].next=head[to],head[to]=yong++; } void build()//构造必要弧 //http://blog.csdn.net/qq172108805/article/details/7783010上有关于这个的简要说明 { int i; for(i=0;i<=t;++i) { if(in[i]>0) adde(ss,i,0,in[i]); else { adde(i,tt,0,-in[i]); sum+=(-in[i]); } } } int sap(int s,int t)//非递归sap { int i,j,ff=0,v,cur[1400],d[1400],num[1400],low[1400],pre[1400]; memset(low,0,sizeof(low)); memset(d,0,sizeof(d)); memset(num,0,sizeof(num)); for(i=0;i<=t;++i) cur[i]=head[i]; low[i=s]=inf; num[s]=t+1; while(d[s]<t+1) { for(j=cur[i];j!=-1;j=e[j].next) if(e[j].f>0&&d[i]==d[v=e[j].v]+1) break; cur[i]=j; if(j>=0) { pre[v]=j; low[v]=e[j].f; if(low[v]>low[i]) low[v]=low[i]; i=v; if(i==t) { for(;i!=s;i=e[pre[i]].u) { e[pre[i]].f-=low[t]; e[pre[i]^1].f+=low[t]; } ff+=low[t]; memset(low,0,sizeof(low)); low[s]=inf; } }else { if(--num[d[i]]==0) break; d[i]=t+1; cur[i]=head[i]; for(j=head[i];j!=-1;j=e[j].next) if(e[j].f>0&&d[i]>d[e[j].v]+1) d[i]=d[e[j].v]+1; num[d[i]]++; if(i!=s) i=e[pre[i]].u; } } return ff; } int d[1400],num[1400]; int min(int a,int b){return a<b?a:b;} int sap_gap(int u,int f,int s,int t)//递归sap { if(u==t) return f; int i,v,mind=t,last=f,cost; for(i=head[u];i!=-1;i=e[i].next) { v=e[i].v; int flow=e[i].f; if(flow>0)//参考模版写的时候把flow写成了f { if(d[u]==d[v]+1) { cost=sap_gap(v,min(last,flow),s,t); e[i].f-=cost; e[i^1].f+=cost; last-=cost; if(d[s]>=t+1) return f-last; if(last==0) break; } if(d[v]<mind) mind=d[v]; } } if(last==f) { --num[d[u]]; if(num[d[u]]==0) d[s]=t+1; d[u]=mind+1; ++num[d[u]]; } return f-last; } int max_f(int s,int t)//调用递归sap { int f=0; memset(d,0,sizeof(d)); memset(num,0,sizeof(num)); for(num[s]=t+1;d[s]<t+1;) f+=sap_gap(s,inf,s,t); return f; } int main() { int i,a,c,b,ng,most,sun; while(scanf("%d%d",&n,&m)!=EOF) { ini(); for(i=0;i<m;i++) { scanf("%d",&a); adde(i,t,a,inf); in[t]+=a; in[i]-=a; } for(;i<m+n;++i) { scanf("%d%d",&ng,&most); adde(s,i,0,most); while(ng--) { scanf("%d%d%d",&a,&b,&c); indexx[ind++]=yong; adde(i,a,b,c); in[a]+=b; in[i]-=b; } } adde(t,s,0,inf); build(); //sun=sap(s,tt);//非递归sap sun=max_f(ss,tt);//递归sap if(sun!=sum) { printf("-1\n"); }else { //sap(s,t);//非递归sap max_f(s,t);//递归sap b=0; for(i=0;i<ind;++i) { a=indexx[i]; b+=e[a].c-e[a].f; } printf("%d\n",b); for(i=0;i<ind;++i) { a=indexx[i]; printf("%d\n",e[a].c-e[a].f); } } printf("\n"); } return 0; }