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. 【Spring】SpringSecurity的使用

    4 SpringSecurity 只需要协助SpringSecurity创建好用户对应的角色和权限组,同时把各个资源所要求的权限信息设定好,剩下的像 "登录验证"."权限 ...

  2. MySQL InnoDB Architecture 简要介绍

    MySQL InnoDB 存储引擎整体架构图: 一.内存存储结构 1.Buffer Pool buffer pool 是主内存中的一块儿存储区域,用于存储访问的表及索引数据.这样从内存中直接访问获取使 ...

  3. node.js基于react项目打包部署到nginx中(Linux服务器)

    1.首先进入React项目目录. 2.执行npm命令进行打包(生成dist包或build包). npm run build 3.将打包的静态文件放入nginx目录中(可以自己新创建一个目录,也可以放在 ...

  4. Java 网络编程 —— 创建多线程服务器

    一个典型的单线程服务器示例如下: while (true) { Socket socket = null; try { // 接收客户连接 socket = serverSocket.accept() ...

  5. 从源码深入理解读写锁(golang-RWMutex)

    环境:go 1.19.8 在读多写少的情况下,即使一段时间内没有写操作,大量并发的读访问也不得不在Mutex的保护下变成串行访问,这种情况下,使用Mutex,对性能影响比较大. 所以就要区分读写操作. ...

  6. 2022-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver

    2022-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver ...

  7. 2022-04-22:给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 ‘X‘ 或者是一个空位 ‘.‘ ,返回在甲板 board 上放置的 战舰 的数量。 战舰

    2022-04-22:给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 board 上放置的 战舰 的数量. 战舰 ...

  8. 2021-10-01:矩阵置零。给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。进阶:一个直观的解决方案是使用 O(mn) 的额外空间

    2021-10-01:矩阵置零.给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 .请使用 原地 算法.进阶:一个直观的解决方案是使用 O(mn) 的额外空间, ...

  9. flask之数据模型flask-sqlalchemy

    一.安装数据库连接依赖包 pip install flask-sqlalchemy pip install pymysql 二.项目配置 app/__init__.py from flask_sqla ...

  10. hadoop 2.7.7 ERROR datanode.DataNode: BlockSender.sendChunks() exception: java.io.IOException: 你的主机中的软件中止了一个已建立的连接。

    最近在测试Hbase在windows上的单机版的功能. 版本:hadoop 2.7.7  hbase 2.0.0 错误: ERROR datanode.DataNode: BlockSender.se ...