CF546E Soldier and Traveling

英文原题:

当然Luogu有中文翻译

对于这种类型的题目,又是增加,又是减少的,我们可以使用网络流进行转化。

说句废话:

网络流这个东西,趣味十足,上可顶替匈牙利算法,下可转化动态规划。它似水一般灵活,总是可以出乎意料地解决问题。

而此题要使用到的是网络最大流Dinic算法

好了,说回来,看到这种题目,你有什么疑惑?

说说我的吧:

  1. 信息这么多(\(a_i\) 和 \(b_i\)),怎么保存?

  2. 这么多的点,无组织,无纪律,怎么办呢?

  3. 这情况也太多了吧,怎么暴搜思考呢?

  4. 即使知道可行,这题的输出怎么办呢?真恶心

我们从网络最大流的角度一个一个来思考吧!

1. 信息这么多,怎么保存?

我们可以把一个点的信息一分为2,让他们整齐罗列。

千万不要误以为 \(a_i\) 和 \(b_i\) 为节点,图中只是形象化地阐述“把一个点的信息一分为2”

2. 这么多的点,无组织,无纪律,怎么办呢?

那就找两个领导把他们汇总起来,这两个领导叫做源点以及汇点

那流量是多少呢?

看图!

看左半部分,点 \(i\) 的流量为 \(a_i\)。

同理,右半部分流量为 \(b_i\)。

中间部分暂不考虑

为什么要这样干呢?

现在假设 \(S\) 点有无穷无尽的水资源。

那么可以往每个左边的河道里塞满水,也就是对于左边的点 \(i\)(图中是靠近红点的四个点)的初始值为 \(a_i\)。

也就是对应题目中“每个点初始时有 \(a_i\) 个人”的条件。

同样的道理,经过中间一番乱七八糟的处理后,从右边流出的水应为 \(b_1,b_2,\dots,b_n\),表示最终处理后,对于右边的点 \(i\) (图中是靠近绿点的四个点)最终为 \(b_i\)。

也就是对应题目中“每个点最终有 \(b_i\) 个人”的条件。

3. 这情况也太多了吧,怎么思考呢?

也就是考虑中间部分。

首先,有些人可以选择留下。那么对于这些点的水,随它们流,连接 \(n\) 条边,流量为 \(+∞\)。

当然,如果有边相连,那也随便流,连接 \(m\) 条边(与题目中的 \(m\) 意义相同),如图(假设有这些边)。

于是乎,跑一遍Dinic算法足矣!

  1. 即使知道可行,这题的输出怎么办呢?真恶心

众所周知,Dinic会在找到增广路时,建立反边,以便反悔。

那么这些反边,就是我们利用的对象。

一条边的反边的权值不就是流过该边的流量吗?

把中间部分的每条反边揪出来,在保存到一个数组里即可。

AC Code

#include <iostream>
#include <cstring>
#include <algorithm>
#include <numeric> const int N = 210, M = 1410, INF = 1e9; struct Node
{
int to;
int next;
int w;
}e[M]; int head[N], cur[N], idx = 1; void add(int a, int b, int c) // 加边
{
idx++;
e[idx].to = b;
e[idx].next = head[a];
e[idx].w = c;
head[a] = idx; idx++;
e[idx].to = a;
e[idx].next = head[b];
e[idx].w = 0;
head[b] = idx;
} int n, m;
int a[N];
int b[N];
int S, T;
int sum1, sum2; // sum1:a sum2:b int d[N]; bool bfs()
{
static int q[N]; // 队列
int hh = 0, tt = 0;
memset(d, 0, sizeof(d));
q[0] = S;
cur[S] = head[S];
d[S] = 1;
while (hh <= tt)
{
int t = q[hh++];
for (int i = head[t]; i; i = e[i].next)
{
int to = e[i].to;
if (!d[to] && e[i].w)
{
cur[to] = head[to];
d[to] = d[t] + 1;
q[++tt] = to;
if (to == T) return true;
}
}
}
return false;
} int dinic(int u, int limit)
{
if (u == T) return limit;
int rest = limit;
for (int i = cur[u]; i && rest; i = e[i].next)
{
cur[u] = i;
int to = e[i].to;
if (d[to] == d[u] + 1 && e[i].w)
{
int k = dinic(to, std::min(rest, e[i].w));
if (!k) d[to] = 0;
rest -= k;
e[i].w -= k;
e[i ^ 1].w += k;
}
}
return limit - rest;
} int map[N][N]; // 记录反边信息,即结果 int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> m;
for (int i = 1; i <= n; i++)std::cin >> a[i];
for (int i = 1; i <= n; i++)std::cin >> b[i];
sum1 = std::accumulate(a + 1, a + n + 1, 0); // 求和
sum2 = std::accumulate(b + 1, b + n + 1, 0);
if(sum1 != sum2) //直接排除
{
std::cout << "NO" << '\n';
return 0;
}
for (int i = 1; i <= n; i++) add(0, i, a[i]); // 左
for (int i = n + 1; i <= n * 2; i++) add(i, n * 2 + 1, b[i - n]); // 右
for (int i = 1; i <= n; i++) add(i, i + n, INF); // 中1
for (int i = 1; i <= m; i++) // 中2
{
int a, b;
std::cin >> a >> b;
add(a, b + n, INF);
add(b, a + n, INF);
}
S = 0, T = n * 2 + 1; auto query = [&]() // Dinic 模板
{
int maxflow = 0, flow = 0;
while (bfs())
{
while (flow = dinic(S, INF))
{
maxflow += flow;
}
}
return maxflow;
}; if (query() != sum1) // 直接排除
{
std::cout << "NO" << '\n';
return 0;
}
else // 扣反边
{
std::cout << "YES" << '\n';
int t = 4 * n + 2;
for (int i = 1; i <= 2 * m + n; i++)
{
map[e[t ^ 1].to][e[t].to - n] += e[t ^ 1].w; // 注意要 -n
t += 2;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
std::cout << map[i][j] << ' ';
}
std::cout << '\n';
}
}
return 0;
}

CF546E Soldier and Traveling 题解的更多相关文章

  1. CF546E Soldier and Traveling(网络流,最大流)

    CF546E Soldier and Traveling 题目描述 In the country there are \(n\) cities and \(m\) bidirectional road ...

  2. CF546E Soldier and Traveling

    题目描述 In the country there are n n n cities and m m m bidirectional roads between them. Each city has ...

  3. Codeforces Round #304 (Div. 2)(CF546E) Soldier and Traveling(最大流)

    题意 给定 n 个城市,m 条边.人只能从走相邻边相连(只能走一次)的城市. 现在给你初始城市的每一个人数,再给一组每个城市人数.询问是否可以从当前人数变换到给定人数.如果能,输入"YES& ...

  4. Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流

    题目链接: http://codeforces.com/problemset/problem/546/E E. Soldier and Traveling time limit per test1 s ...

  5. Soldier and Traveling

    B. Soldier and Traveling Time Limit: 1000ms Memory Limit: 262144KB 64-bit integer IO format: %I64d   ...

  6. 【codeforces 546E】Soldier and Traveling

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  7. 网络流(最大流) CodeForces 546E:Soldier and Traveling

    In the country there are n cities and m bidirectional roads between them. Each city has an army. Arm ...

  8. 「日常训练」 Soldier and Traveling (CFR304D2E)

    题意 (CodeForces 546E) 对一个无向图,给出图的情况与各个节点的人数/目标人数.每个节点的人只可以待在自己的城市或走到与他相邻的节点. 问最后是否有解,输出一可行解(我以为是必须和答案 ...

  9. Codeforces 546E Soldier and Traveling(最大流)

    题目大概说一张无向图,各个结点初始有ai人,现在每个人可以选择停留在原地或者移动到相邻的结点,问能否使各个结点的人数变为bi人. 如此建容量网络: 图上各个结点拆成两点i.i' 源点向i点连容量ai的 ...

  10. 【CF】304 E. Soldier and Traveling

    基础网络流,增加s和t,同时对于每个结点分裂为流入结点和流出结点.EK求最大流,判断最大流是否等于当前总人数. /* 304E */ #include <iostream> #includ ...

随机推荐

  1. MySQL MHA信息的收集【Filebeat+logstash+MySQL】

    一.项目背景 随着集团MHA集群的日渐增长,MHA管理平台话越来越迫切.而MHA平台的建设第一步就是将这些成百上千套的MHA集群信息收集起来,便于查询和管理. MHA主要信息如下: (1)基础配置信息 ...

  2. 解决flex布局中justify-content设置成space-between后因数据问题导致最后一行布局错乱

    在常用的flex布局中,当页面展示商品时,因为数据的不确定,导致justify-content设置成space-between,最后一行布局错乱 1 <!DOCTYPE html> 2 & ...

  3. EasyExcel配置步骤

    1.介绍 EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项目 参考 https://blog.csdn.net/u013044713/article/details/1202 ...

  4. 2009年NOIP提高组真题-HanKson的趣味题(GCD&LCM优化)

    2009年NOIP提高组真题-HanKson的趣味题(GCD&LCM优化) 本题的编码是用Python实现的,C++的思路也是相同的. 希望本文能够帮助到你! 题目: 暴力法: 直接根据题目的 ...

  5. python-SSTI模板注入

    一.python_SSTI模板注入介绍 ssti漏洞成因 ssti服务端模板注入,ssti主要为python的一些框架 jinja2 mako tornado django,PHP框架smarty t ...

  6. 是时候,升级你的 Windows 了「GitHub 热点速览」

    不知道多少小伙伴用着 Windows 操作系统,可能会有一个烦恼是有时候操作系统过慢,因为众多拖慢 Windows 系统的组件.Atlas 作为一个修改版的 Windows 系统,能极大提高操作系统运 ...

  7. 用R语言进行时间序列ARMA模型分析

    应用时间序列 时间序列分析是一种重要的数据分析方法,应用广泛.以下列举了几个时间序列分析的应用场景: 1.经济预测:时间序列分析可以用来分析经济数据,预测未来经济趋势和走向.例如,利用历史股市数据和经 ...

  8. 带大小写忽略的Replace

    #region 以下函数用于忽略大小写替换操作 public static string Replace(string Expression, string Find, string Replacem ...

  9. #Python 缺失值的检测与处理,处理部分

  10. 2023-04-19:给定一个非负数组arr 任何两个数差值的绝对值,如果arr中没有,都要加入到arr里 然后新的arr继续,任何两个数差值的绝对值,如果arr中没有,都要加入到arr里 一直到ar

    2023-04-19:给定一个非负数组arr 任何两个数差值的绝对值,如果arr中没有,都要加入到arr里 然后新的arr继续,任何两个数差值的绝对值,如果arr中没有,都要加入到arr里 一直到ar ...