有汇源上下界最大流模板
作者:互联网
题目描述:
在接下来的n天中,射命丸文将要拍摄幻想乡的少女的照片并且从中为第x个少女拍摄至少Gx张照片刊登在《文文。新闻》上。在第k天的时候文文有Ck个取材对象,且对于每个取材对象拍的照片必须在闭区间[Lki,Rki]中。如果过少,
文文就搞不出大新文;如果过多,就会有少女很安格瑞。除此之外,因为拍照设备的原因,对于第i天,每天的拍照数量不能超过Di张。在满足这些限定的条件下,文文希望拍到的照片尽可能地多。
由于文文需要去取材,因此她把这个任务交给了你,让你帮她去解决。
思路:模板题,把n天和少女看成节点,源点对每天连边,容量为Di,每天再与可以拍照的少女连边,容量为up-down,每个少女至少要拍Gx张照片,少女要对汇点连容量为INT-Gx的边,这里还没理解到,
汇点再对源点连水泵边(容量为inf),上述连边的同时要求出imo[i],即每个点的所连边的流入流量-流出流量,再建立新的源点和汇点,然后按照无汇源上下界可行流的连边方法,求出最大可行流,
如果最大可行流是等于新源点的所有出边的流量总和,说明少女的最少照片Gx得到了满足,然后再删除水泵边,跟换为最初的源点和汇点,把剩余残存流量榨干,与最大可行流相加就得到了最大流。
code:
int n, m, s1, t1; int imo[maxn];//入边流量-出边流量 int main() { while (~scanf("%d%d", &n, &m)) { memset(hd, 0, sizeof(hd)); tot = 1; memset(imo, 0, sizeof(imo)); s1 = n + m + 1, t1 = s1 + 1; s = t1 + 1, t = s + 1; for (int i = n+1; i <= n+m; i++) { int g; scanf("%d", &g); add(i, t1, inf - g); imo[i] -= g; imo[t1] += g; } for (int i = 1; i <= n; i++) { int c, d; scanf("%d%d", &c, &d); add(s1, i, d); while (c--) { int a, l, r; scanf("%d%d%d", &a, &l, &r); a++; add(i, a + n, r - l); imo[i] -= l;//注意这里是下届 imo[a + n] += l; } } int cnt = 0; for (int i = 1; i <= n + m + 2; i++) { if (imo[i] > 0) { add(s, i, imo[i]); cnt+=imo[i]; } else { add(i, t, -imo[i]); } } add(t1, s1, inf);//水泵 if (dinic()!= cnt) {//判断少女的最少拍照数得到满足 printf("-1\n\n"); } else { s = s1, t = t1;//更换源点汇点 int res = e[tot].flow;//反向边就是s1->t1的可行最大流 e[tot].flow = 0; e[tot - 1].flow = 0;//去掉水泵边 printf("%lld\n\n", dinic() + res);//榨干残留网络 } } return 0; }
标签:少女,汇源,s1,源点,imo,下界,文文,t1,模板 来源: https://www.cnblogs.com/MYMYACMer/p/14793225.html