F - Breakdown
F - Breakdown
Problem Statement
You are given a simple undirected graph consisting of vertices and edges. For , the -th edge connects vertices and . Also, for , vertex is assigned a positive integer , and there are pieces placed on it.
As long as there are pieces on the graph, repeat the following operation:
- First, choose and remove one piece from the graph, and let be the vertex on which the piece was placed.
- Choose a (possibly empty) set of vertices adjacent to such that , and place one piece on each vertex in .
Print the maximum number of times the operation can be performed.
It can be proved that, regardless of how the operation is performed, there will be no pieces on the graph after a finite number of iterations.
Constraints
- All input values are integers.
Input
The input is given from Standard Input in the following format:
Output
Print the answer.
Sample Input 1
6 6
1 2
2 3
3 1
3 4
1 5
5 6
9 2 3 1 4 4
1 0 0 0 0 1
Sample Output 1
5
In the following explanation, let represent the numbers of pieces on the vertices. Initially, .
Consider performing the operation as follows:
- Remove one piece from vertex and place one piece each on vertices and . Now, .
- Remove one piece from vertex . Now, .
- Remove one piece from vertex . Now, .
- Remove one piece from vertex and place one piece on vertex . Now, .
- Remove one piece from vertex . Now, .
In this procedure, the operation is performed five times, which is the maximum possible number of times.
Sample Input 2
2 1
1 2
1 2
0 0
Sample Output 2
0
In this sample input, there are no pieces on the graph from the beginning.
Sample Input 3
10 20
4 8
1 10
1 7
5 9
9 10
8 10
7 5
1 4
7 3
8 7
2 8
5 8
4 2
5 1
7 2
8 3
3 4
8 9
7 10
2 3
25 5 1 1 16 5 98 3 21 1
35 39 32 11 35 37 14 29 36 1
Sample Output 3
1380
解题思路
假设现在已经知道每个节点 上仅有一个棋子时能执行的最大操作次数 ,那么答案就是 。由于每次只能往比自身权值小的相邻节点放置一个棋子,因此状态转移是没有环的,可以用 dp 求出每个 。
关于 的最大值,相当于从所有权值小于 的相邻节点中,选出总权值不超过 的具有最大操作次数的点集,这就是 01 背包的定义。用 表示前 个权值不超过 的相邻节点中,总权值不超过 的所有点集中操作次数的最大值,状态转移方就是 。 表示 的相邻节点里面权值小于 的节点数量。因此 就是最后要求的最大操作次数。
最后还需要与 01 背包一样优化掉第一维,防止爆空间。初始时令 。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5010, M = N * 2;
int h[N], e[M], ne[M], idx;
int w[N], a[N];
int f[N][N];
void add(int u, int v) {
e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}
int dfs(int u, int p) {
if (f[u][w[u] - 1]) return f[u][w[u] - 1];
for (int i = 0; i < w[u]; i++) {
f[u][i] = 1;
}
for (int i = h[u]; i != -1; i = ne[i]) {
if (e[i] != p) {
for (int j = w[u] - 1; j >= w[e[i]]; j--) {
f[u][j] = max(f[u][j], f[u][j - w[e[i]]] + dfs(e[i], u));
}
}
}
return f[u][w[u] - 1];
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
memset(h, -1, sizeof(h));
while (m--) {
int u, v;
scanf("%d %d", &u, &v);
add(u, v), add(v, u);
}
for (int i = 1; i <= n; i++) {
scanf("%d", w + i);
}
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
LL ret = 0;
for (int i = 1; i <= n; i++) {
ret += 1ll * dfs(i, -1) * a[i];
}
printf("%lld", ret);
return 0;
}
参考资料
Editorial - Toyota Programming Contest 2024#2(AtCoder Beginner Contest 341):https://atcoder.jp/contests/abc341/editorial/9337
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18019490
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-02-18 D. Triangle Coloring
2023-02-18 约数之和
2022-02-18 地宫取宝