先导知识

无源汇有上下界可行流

题目链接

https://vjudge.net/problem/ZOJ-3229

https://www.luogu.com.cn/problem/P5192 (有改动)

题目大意

多组数据,读到文件结束。

对于每一组数据,第一行为正整数\(n,m\)表示\(n\)天,\(m\)个少女。

接下来一行,\(m\)个正整数\(G_1,G_2 ... G_m\)分别表示每个少女总共至少要拍的照片张数。

接下来\(n\)组,每一组第一行有两个整数\(C_i,D_i\),表示这一天有\(C_i\)个少女要拍照,这一天的照片总数不超过\(D_i\)。

接着有\(C_i\)行,每行三个整数\(k,L_k,R_k\),表示在这一天里\(k\)号少女要拍的照片数目处于\([L_k,R_k]\)区间。

(注意少女是从\(0\)开始编号的。)

满足这些条件以后,所有天的照片总数越多越好

如果有解输出照片总数,并按顺序输出每一天的少女拍照数目,否则输出\(-1\),每组答案后输出一空行。

题目解析

这道题比较抽象,不是经典的模板,还需要经过一些变换,才可以变成裸的模板题。

题目为有源汇有上下界的最大流模板。

首先,对\(n\)天,每一天照片数存量\(\leq D_i\);\(m\)个少女,每个少女照片数消耗\(\geq G_k\)。

若将每一天、每个少女看作点,则有上下限点权要求。

其次,每一天中,少女消耗照片数有\([L,R]\)限制,可看成从“天”的点集到“少女”点集的一条有向边。

那么,初步建立了一张二分图,分为“天”、“少女”两部分点集\(A,B\),有向边方向一定是\(A \rightarrow B\)。

为了便于直观理解,这里选用了例题中的第一组 Sample Input 的数据进行绘图讲解。

将两个点集中“点权”的上下限看作从虚拟源点 \(s\) 流出或流入虚拟汇点 \(t\) 的“边权”上下限要求,就可以建好了一张“有源汇”的图,结合题目要求,我们知道当前任务转化为了这张图上的 有源汇有上下界最大流

接下来,怎样转化为我们熟悉的问题呢?

在“无源汇有上下界可行流”中,每一个结点都满足 流量平衡

但是在“有源汇”的图中,源点 \(s\) 及汇点 \(t\) 是不满足流量平衡的,这时,我们可以考虑连接一条从汇点 \(t\) 到源点 \(s\) 的,容量为 \(\infty\) 的有向边。

这样,既满足了源点 \(s\) 流出和汇点 \(t\) 流入无限的性质,又能使整张网络图上的点全都满足流量平衡,即转化成为了“无源汇”的问题。

根据解决“无源汇有上下界可行流”的方法,(用下界流填满各点,盈余为正者与新设虚拟源点 \(s'\) 相连,盈余为负者与新设虚拟汇点 \(t'\) 相连),可以查看 上一篇博客解决的无源汇有上下界可行流问题 进行回顾。

可以得到新图的“可行流”,再去除虚设的源汇,再跑一次最大流,即可得到本题的答案了,即,有源汇有上下界最大流。

各位读者可以根据样例,自行建图加深理解。

网络流的题目,一般只需要套用模板,而思维难点,往往在于将抽象问题转化为建有向图解决,需要多加练习。

后面博客会陆续更新,经典例题 网络流 \(24\) 题 的部分解题策略,欢迎浏览支持,多多指教!

参考代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1405;
const int INF = 2147483647;
struct Edge{
int from, to, cap, flow, min;
};
int n, m, s, t, gap[N], cur[N], dep[N], R[N], cnt;
vector <Edge> e;
vector <int> G[N]; void init()
{
memset(gap, 0, sizeof gap);
memset(cur, 0, sizeof cur);
memset(dep, 0, sizeof dep);
++gap[dep[t] = 1];
queue <int> Q;
Q.push(t);
while (!Q.empty()) {
int x=Q.front(); Q.pop();
for (int i = 0; i < G[x].size(); i++)
{
int v = e[G[x][i]].to;
if (!dep[v])
{
++gap[dep[v] = dep[x]+1];
Q.push(v);
}
}
}
}
int augment(int x, int a)
{
if (x == t || !a) return a;
int flow = 0;
for (int &i=cur[x]; i < G[x].size(); i++)
{
Edge& b = e[G[x][i]];
if (dep[x] == dep[b.to] + 1 && b.cap > b.flow) {
int tmp = augment(b.to, min(a, b.cap - b.flow));
flow += tmp;
a -= tmp;
b.flow += tmp;
e[G[x][i]^1].flow -= tmp;
if (!a) return flow;
}
}
if (!(--gap[dep[x]])) dep[s] = cnt+1;
++gap[++dep[x]], cur[x] = 0;
return flow;
}
ll maxFlow()
{
init();
ll ans = 0;
while (dep[s] <= cnt) ans += augment(s, INF);
return ans;
}
void Clear()
{
e.clear();
for (int i = 0; i <= cnt; ++i) G[i].clear();
memset(R, 0, sizeof R);
n = m = s = t = cnt = 0;
}
void addEdge(int u, int v, int l, int c, int i)
{
e.push_back((Edge){u, v, c-l, 0, l});
e.push_back((Edge){v, u, 0, 0, 0});
G[u].push_back(i);
G[v].push_back(i^1);
R[u] -= l;
R[v] += l;
}
int main()
{
int T = 0;
while (scanf("%d%d", &n, &m) == 2)
{ int s1, t1;
s1 = n + m + 1, t1 = s1 + 1;
s = s1 + 2, t = t1 + 2; for (int i = 0; i < m; ++i) {
int a;
scanf("%d", &a);
addEdge(i+1, t1, a, INF, i << 1);
} int j = m-1;
for (int i = m+1; i <= m+n; ++i) {
int a, c, l, k;
scanf("%d%d", &k, &a);
addEdge(s1, i, 0, a, (++j) << 1);
while (k--)
{
scanf("%d%d%d", &a, &l, &c);
addEdge(i, a+1, l, c, (++j) << 1);
}
} int k = j;
for (int i = 1; i < s; ++i) {
if (R[i] > 0) addEdge(s, i, 0, R[i], (++k) << 1);
else if (R[i] < 0) addEdge(i, t, 0, -R[i], (++k) << 1);
} addEdge(t1, s1, 0, INF, (++k) << 1);
cnt = n+m+4;
ll a = maxFlow(); // printf("maxflow = %lld\n", a);
// for (int i = 0; i <= j; ++i) {
// printf("%d -> %d (%d/%d)\n", e[i << 1].from, e[i << 1].to, e[i << 1].flow, e[i << 1].cap);
// } //这一部分查看可以看新图的流量情况 int flag = 0;
for (int i = 0; i < G[s].size(); ++i) {
if (e[G[s][i]].cap > e[G[s][i]].flow) {flag = 1; break;}
}
if (flag) printf("-1\n");
else {
s = s1, t = t1;
printf("%lld\n", maxFlow());
for (int i = m+1; i <= j; ++i) {
if (e[i << 1].from > m && e[i << 1].to <= m) printf("%d\n", e[i << 1].flow+e[i << 1].min);
}
}
Clear();
putchar('\n');
}
return 0;
}

感谢支持!

【模板】有源汇有上下界最大流(网络流)/ZOJ3229的更多相关文章

  1. LOJ.117.[模板]有源汇有上下界最小流(Dinic)

    题目链接 有源汇有上下界最小流 Sol1. 首先和无源汇网络流一样建图,求SS->TT最大流: 然后连边(T->S,[0,INF]),再求一遍SS->TT最大流,答案为新添加边的流量 ...

  2. LOJ.116.[模板]有源汇有上下界最大流(Dinic)

    题目链接 http://blog.csdn.net/just_sort/article/details/75448403 有源汇有上下界网络流 通过添加一条(T->S,[0,INF])的边变成无 ...

  3. 【LOJ116】有源汇有上下界最大流(模板题)

    点此看题面 大致题意: 给你每条边的流量上下界,让你先判断是否存在可行流.若存在,则输出最大流. 无源汇上下界可行流 在做此题之前,最好先去看看这道题目:[LOJ115]无源汇有上下界可行流. 大致思 ...

  4. LOJ116 - 有源汇有上下界最大流

    原题链接 Description 模板题啦~ Code //有源汇有上下界最大流 #include <cstdio> #include <cstring> #include & ...

  5. 【Loj116】有源汇有上下界最大流(网络流)

    [Loj116]有源汇有上下界最大流(网络流) 题面 Loj 题解 模板题. #include<iostream> #include<cstdio> #include<c ...

  6. loj #116. 有源汇有上下界最大流

    题目链接 有源汇有上下界最大流,->上下界网络流 注意细节,重置cur和dis数组时,有n+2个点 #include<cstdio> #include<algorithm> ...

  7. loj #117. 有源汇有上下界最小流

    题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...

  8. [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流

    poj原题 zoj原题 //注意zoj最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...

  9. LibreOJ #116. 有源汇有上下界最大流

    二次联通门 : LibreOJ #116. 有源汇有上下界最大流 /* LibreOJ #116. 有源汇有上下界最大流 板子题 我也就会写写板子题了.. 写个板子第一个点还死活过不去... 只能打个 ...

随机推荐

  1. stm32学习心得体会

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...

  2. linux shell 函数返回值问题(超过255)

    最近再写一个shell测试的时候出现问题,函数返回值异常 用shell计算斐波那契数列数列,写了一个shell函数,然后调用的,验证的时候我只随便计算了几个数(10以内),确认结果是正确的就提交了,后 ...

  3. pku 2425 A Chess Game (SG)

    题意: 给一个由N个点组成的一张有向图,不存在环.点的编号是0~N-1. 然后给出M个棋子所在的位置(点的编号)[一个点上可同时有多个棋子]. 每人每次可移动M个棋子中的一个棋子一步,移动方向是有向边 ...

  4. 计算机网络漫谈之IP数据包

    网络层从 网络层 .IP与子网掩码 前前后后我们也说了两次了,IP 这个东西絮絮叨叨的也一直在提.今天我们来解开IP协议的面纱,还记得我们之前在数据链路层说的物理帧的结构吗?就是这样: 其中Head叫 ...

  5. C 函数指针语法总结

    C 函数指针语法总结 函数指针 定义 每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针. 注意:函数指针的本质是一个指针变量,且指针指向的函数的入口地址. 语法 返 ...

  6. js 实现边缘撞击检测动画

    js 实现边缘撞击检测动画 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  7. Mysql - 如何存储 10位、13位的 unix 时间戳?

    背景 前面有讲过存日期时间可以用  datetime.timestamp 类型:https://www.cnblogs.com/poloyy/p/15546735.html 格式是: YYYY-MM- ...

  8. Windows应用开发中程序窗口中的各种图标尺寸规划

    为了让你的图标在各个视图模式下都能有合适的尺寸,需要制作4种尺寸16x16.32x32.48x48.256x256 在Windows系统中,几乎所有窗口都是ListView,其中的图标都按照指定的尺寸 ...

  9. Pycharm下载安装详细教程

    目录 1.Pycharm 简介 2.Pycharm下载 3.环境变量的配置 4.Pycharm的使用 1.Pycharm 简介 PyCharm是一种Python IDE(Integrated Deve ...

  10. ICCV2021 | Vision Transformer中相对位置编码的反思与改进

    ​前言  在计算机视觉中,相对位置编码的有效性还没有得到很好的研究,甚至仍然存在争议,本文分析了相对位置编码中的几个关键因素,提出了一种新的针对2D图像的相对位置编码方法,称为图像RPE(IRPE). ...