CF546E Soldier and Traveling 题解
CF546E Soldier and Traveling
英文原题:

对于这种类型的题目,又是增加,又是减少的,我们可以使用网络流进行转化。
说句废话:
网络流这个东西,趣味十足,上可顶替匈牙利算法,下可转化动态规划。它似水一般灵活,总是可以出乎意料地解决问题。
好了,说回来,看到这种题目,你有什么疑惑?
说说我的吧:
信息这么多(\(a_i\) 和 \(b_i\)),怎么保存?
这么多的点,无组织,无纪律,怎么办呢?
这情况也太多了吧,怎么暴搜思考呢?
即使知道可行,这题的输出怎么办呢?真恶心
我们从网络最大流的角度一个一个来思考吧!
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算法足矣!
- 即使知道可行,这题的输出怎么办呢?真恶心
众所周知,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 题解的更多相关文章
- CF546E Soldier and Traveling(网络流,最大流)
CF546E Soldier and Traveling 题目描述 In the country there are \(n\) cities and \(m\) bidirectional road ...
- CF546E Soldier and Traveling
题目描述 In the country there are n n n cities and m m m bidirectional roads between them. Each city has ...
- Codeforces Round #304 (Div. 2)(CF546E) Soldier and Traveling(最大流)
题意 给定 n 个城市,m 条边.人只能从走相邻边相连(只能走一次)的城市. 现在给你初始城市的每一个人数,再给一组每个城市人数.询问是否可以从当前人数变换到给定人数.如果能,输入"YES& ...
- 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 ...
- Soldier and Traveling
B. Soldier and Traveling Time Limit: 1000ms Memory Limit: 262144KB 64-bit integer IO format: %I64d ...
- 【codeforces 546E】Soldier and Traveling
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 网络流(最大流) CodeForces 546E:Soldier and Traveling
In the country there are n cities and m bidirectional roads between them. Each city has an army. Arm ...
- 「日常训练」 Soldier and Traveling (CFR304D2E)
题意 (CodeForces 546E) 对一个无向图,给出图的情况与各个节点的人数/目标人数.每个节点的人只可以待在自己的城市或走到与他相邻的节点. 问最后是否有解,输出一可行解(我以为是必须和答案 ...
- Codeforces 546E Soldier and Traveling(最大流)
题目大概说一张无向图,各个结点初始有ai人,现在每个人可以选择停留在原地或者移动到相邻的结点,问能否使各个结点的人数变为bi人. 如此建容量网络: 图上各个结点拆成两点i.i' 源点向i点连容量ai的 ...
- 【CF】304 E. Soldier and Traveling
基础网络流,增加s和t,同时对于每个结点分裂为流入结点和流出结点.EK求最大流,判断最大流是否等于当前总人数. /* 304E */ #include <iostream> #includ ...
随机推荐
- python选出一定数量的随机文件到某个文件夹
import os import random import shutil def move_file(target_path, save_path, number): file_list = os. ...
- Java:如何加密或解密PDF文档?
在工作中,我们会将重要的文档进行加密,并且设置用户的访问权限,其他外部人员均无法打开,只有获取该权限的用户才有资格打开文档.此外,限制用户的使用权限,极大程度上阻止了那些有意要篡改.拷贝其中内容的人, ...
- Go语言实现基于HTTP的内存缓存服务
所有的缓存数据都存储在服务器的内存中,因此重启服务器会导致数据丢失,基于HTTP通信会将使开发变得简单,但性能不会太好 缓存服务接口 本程序采用REST接口,支持设置(Set).获取(Get)和删除( ...
- SRE中的SLA/SLO/SLI
SLA通俗理解 SLA 表征服务方与客户间的服务等级协议,定义服务方需保证的服务质量以及不达标情况下的服务补偿,在SRE领域,SLA 细分为 SLI.SLO 与 SLA: SLI,服务质量指标,服务的 ...
- 读《图解HTTP》
最近读了一本书<图解HTTP>,读完后在大体上对HTTP协议有了更深层次的了解.以下是我以前不懂的问题,通过阅读此书后,这些问题都有了答案: 问题: URI和URL的区别? cookie到 ...
- selenium IDE插件的配置使用
开头 Selenium提供了一个可以自动录制脚本的插件 叫selenium IDE 让我们一起看看如何安装使用 安装 因为google扩展商城大多数人用不了,所以我们选用的是edag来下载seleni ...
- 2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru
2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法. 宏使用如下: #[derive(Builder)] pub stru ...
- 2021-11-02:生命游戏。根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个
2021-11-02:生命游戏.根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机.给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个 ...
- 2021-11-01:寻找重复数。给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设 nums 只有 一个重复的整数
2021-11-01:寻找重复数.给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设 nums 只有 一个重复的整数 ...
- Django4全栈进阶之路3 apps.py 文件
在 Django 4 中,每个应用(app)都需要定义一个 apps.py 文件,用于配置应用的基本信息,如应用的名称.显示名称.图标.默认路径.启动时需要执行的操作等.apps.py 文件是一个 P ...