首页 > 其他分享 >F - Breakdown

F - Breakdown

时间:2024-02-18 16:37:43浏览次数:26  
标签:Breakdown 10 int vertex Sample leq piece

F - Breakdown

Problem Statement

You are given a simple undirected graph consisting of $N$ vertices and $M$ edges. For $i = 1, 2, \ldots, M$, the $i$-th edge connects vertices $u_i$ and $v_i$. Also, for $i = 1, 2, \ldots, N$, vertex $i$ is assigned a positive integer $W_i$, and there are $A_i$ 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 $x$ be the vertex on which the piece was placed.
  • Choose a (possibly empty) set $S$ of vertices adjacent to $x$ such that $\sum_{y \in S} W_y \lt W_x$, and place one piece on each vertex in $S$.

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.
  • $2 \leq N \leq 5000$
  • $1 \leq M \leq \min \lbrace N(N-1)/2, 5000 \rbrace$
  • $1 \leq u_i, v_i \leq N$
  • $u_i \neq v_i$
  • $i \neq j \implies \lbrace u_i, v_i \rbrace \neq \lbrace u_j, v_j \rbrace$
  • $1 \leq W_i \leq 5000$
  • $0 \leq A_i \leq 10^9$

Input

The input is given from Standard Input in the following format:

$N$ $M$
$u_1$ $v_1$
$u_2$ $v_2$
$\vdots$
$u_M$ $v_M$
$W_1$ $W_2$ $\ldots$ $W_N$
$A_1$ $A_2$ $\ldots$ $A_N$

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 $A = (A_1, A_2, \ldots, A_N)$ represent the numbers of pieces on the vertices. Initially, $A = (1, 0, 0, 0, 0, 1)$.

Consider performing the operation as follows:

  • Remove one piece from vertex $1$ and place one piece each on vertices $2$ and $3$. Now, $A = (0, 1, 1, 0, 0, 1)$.
  • Remove one piece from vertex $2$. Now, $A = (0, 0, 1, 0, 0, 1)$.
  • Remove one piece from vertex $6$. Now, $A = (0, 0, 1, 0, 0, 0)$.
  • Remove one piece from vertex $3$ and place one piece on vertex $2$. Now, $A = (0, 1, 0, 0, 0, 0)$.
  • Remove one piece from vertex $2$. Now, $A = (0, 0, 0, 0, 0, 0)$.

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

 

解题思路

  假设现在已经知道每个节点 $u$ 上仅有一个棋子时能执行的最大操作次数 $f_u$,那么答案就是 $\sum\limits_{u=1}^{n}{f_u \cdot a_u}$。由于每次只能往比自身权值小的相邻节点放置一个棋子,因此状态转移是没有环的,可以用 dp 求出每个 $f_u$。

  关于 $f_u$ 的最大值,相当于从所有权值小于 $w_u$ 的相邻节点中,选出总权值不超过 $w_u - 1$ 的具有最大操作次数的点集,这就是 01 背包的定义。用 $f_u(i,j)$ 表示前 $i$ 个权值不超过 $w_u - 1$ 的相邻节点中,总权值不超过 $j$ 的所有点集中操作次数的最大值,状态转移方就是 $f_u(i,j) = \max\left\{{f_u(i-1,j),\,f_u(i-1,j-w_v)+f_v(s_v,w_v-1)}\right\}$。$s_v$ 表示 $v$ 的相邻节点里面权值小于 $w_v$ 的节点数量。因此 $f_u(s_u, w_u-1)$ 就是最后要求的最大操作次数。

  最后还需要与 01 背包一样优化掉第一维,防止爆空间。初始时令 $f_u(j) = 1, \, j \in [0, w_u-1]$。

  AC 代码如下,时间复杂度为 $O(m \cdot W)$:

#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

标签:Breakdown,10,int,vertex,Sample,leq,piece
From: https://www.cnblogs.com/onlyblues/p/18019490

相关文章

  • 什么是工作分解结构?What Work Breakdown Structure?
    一个​​工作分解结构(WBS)​​是由项目团队完成项目目标并创造必要的交付执行工作的一个面向交付分层分解。WBS是有效项目规划,执行,控制,监控和报告的基石。WBS中包含的所有工......