AtCoder Weekday Contest 0035 Beta题解(AWC 0035 Beta A-E)

A - Warehouse Inventory Management

【题目来源】

AtCoder:A - Warehouse Inventory Management

【题目描述】

Takahashi works in the logistics department of a company. The company has \(N\) warehouses, numbered from warehouse \(1\) to warehouse \(N\). Each warehouse \(i\) \((1 \leq i \leq N)\) currently stores \(P_i\) items.
高桥在一家公司的物流部门工作。该公司有 \(N\) 个仓库,编号从 \(1\)\(N\)。每个仓库 \(i\)\(1 \leq i \leq N\))目前存储了 \(P_i\) 件货物。

Today, \(M\) shipping instructions to move items between warehouses have been issued. The \(j\)-th \((1 \leq j \leq M)\) shipping instruction is "move \(W_j\) items from warehouse \(U_j\) to warehouse \(V_j\)." Here, \(U_j \neq V_j\). There may be multiple shipping instructions between the same pair of warehouses.
今天,下达了 \(M\) 条在仓库间移动货物的指令。第 \(j\) 条(\(1 \leq j \leq M\))指令是"从仓库 \(U_j\) 移动 \(W_j\) 件货物到仓库 \(V_j\)"。这里,\(U_j \neq V_j\)。同一对仓库之间可能有多条移动指令。

The \(M\) shipping instructions are applied all at once, not sequentially. That is, the final number of items in each warehouse is obtained by taking the initial number of items, adding the total number of items coming into that warehouse, and subtracting the total number of items going out of that warehouse.
\(M\) 条指令是同时生效的,而不是顺序执行的。也就是说,每个仓库的最终货物数量是通过初始货物数量加上进入该仓库的货物总数,再减去从该仓库运出的货物总数得到的。

Takahashi wants to find the warehouse number with the most items after all shipping instructions have been applied. If there are multiple warehouses with the most items, find the one with the smallest warehouse number.
高桥希望找出在所有指令生效后,货物数量最多的仓库编号。如果有多个仓库的货物数量同为最多,则输出编号最小的仓库编号。

【输入】

\(N\) \(M\)
\(P_1\) \(P_2\) \(\ldots\) \(P_N\)
\(U_1\) \(V_1\) \(W_1\)
\(U_2\) \(V_2\) \(W_2\)
\(\vdots\)
\(U_M\) \(V_M\) \(W_M\)

  • The first line contains the number of warehouses \(N\) and the number of shipping instructions \(M\), separated by a space.
  • The second line contains the initial number of items in each warehouse \(P_1, P_2, \ldots, P_N\), separated by spaces.
  • The following \(M\) lines contain the details of each shipping instruction. If \(M = 0\), this part is not given.
  • The \(j\)-th line \((1 \leq j \leq M)\) contains the source warehouse number \(U_j\), the destination warehouse number \(V_j\), and the number of items to move \(W_j\) for the \(j\)-th shipping instruction, separated by spaces.

【输出】

Print on one line the warehouse number with the most items after all shipping instructions have been applied. If there are multiple warehouses with the most items, print the one with the smallest number.

【输入样例】

3 2
10 20 30
1 2 5
3 2 10

【输出样例】

2

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, m, p[N];  // n: 人数, m: 交易次数, p: 每个人的净收入
struct Node
{
    int u, v, w;
} a[N];
signed main()
{
    cin >> n >> m;  // 输入人数和交易次数
    for (int i = 1; i <= n; i++)  // 输入初始金额
    {
        cin >> p[i];
    }
    for (int i = 1; i <= m; i++)  // 处理交易
    {
        int u, v, w;
        cin >> u >> v >> w;  // 从u给v转账w
        p[u] -= w;  // u减少w
        p[v] += w;  // v增加w
    }
    // 调试输出
    // for (int i=1; i<=n; i++)
    //     cout << p[i] << " ";
    // cout << endl;
    
    int maxn = -1, maxi = -1;  // 最大净收入和对应的人
    for (int i = 1; i <= n; i++)  // 查找最大净收入
    {
        if (p[i] > maxn)
        {
            maxn = p[i];
            maxi = i;
        }
    }
    cout << maxi << endl;  // 输出净收入最大的人的编号
    return 0;
}

【运行结果】

3 2
10 20 30
1 2 5
3 2 10
2

B - Package Distribution Center

【题目来源】

AtCoder:B - Package Distribution Center

【题目描述】

Takahashi works at a delivery company. Today, he needs to deliver \(N\) packages to their designated destinations. The destination of the \(i\)-th package is at coordinate \(D_i\) on a number line.
高桥在一家快递公司工作。今天,他需要将 \(N\) 个包裹送达指定目的地。第 \(i\) 个包裹的目的地位于数轴上的坐标 \(D_i\)

This delivery company has \(M\) distribution centers, and the \(j\)-th distribution center is located at coordinate \(S_j\) on the number line. Each package departs from exactly one distribution center and is transported to its destination. The cost of transporting package \(i\) from distribution center \(j\) to its destination is the distance \(|D_i - S_j|\).
这家快递公司有 \(M\) 个配送中心,第 \(j\) 个配送中心位于数轴上的坐标 \(S_j\)。每个包裹恰好从一个配送中心出发,运输到其目的地。将包裹 \(i\) 从配送中心 \(j\) 运送到目的地的成本是距离 \(|D_i - S_j|\)

Each package must be assigned to exactly one distribution center. However, a single distribution center may handle multiple packages, and there may be distribution centers that handle no packages at all.
每个包裹必须分配到一个配送中心。但是,一个配送中心可以处理多个包裹,也可能存在不处理任何包裹的配送中心。

Minimize the total delivery cost of all packages.
最小化所有包裹的总运输成本。

That is, when assigning a distribution center \(f(i)\) (\(1 \leq f(i) \leq M\)) to each package \(i\) (\(1 \leq i \leq N\)), find the minimum value of
也就是说,当为每个包裹 \(i\)\(1 \leq i \leq N\))分配一个配送中心 \(f(i)\)\(1 \leq f(i) \leq M\))时,求

\(\sum_{i=1}^{N} |D_i - S_{f(i)}|\)

【输入】

\(N\) \(M\)
\(D_1\) \(D_2\) \(\ldots\) \(D_N\)
\(S_1\) \(S_2\) \(\ldots\) \(S_M\)

  • The first line contains \(N\), the number of packages, and \(M\), the number of distribution centers, separated by a space.
  • The second line contains \(D_1, D_2, \ldots, D_N\), the coordinates of each package's destination, separated by spaces.
  • The third line contains \(S_1, S_2, \ldots, S_M\), the coordinates of each distribution center, separated by spaces.

【输出】

Print the minimum total delivery cost on a single line.

【输入样例】

3 2
1 4 7
3 6

【输出样例】

4

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, m, ans;  // n: 任务数, m: 机器数, ans: 最小总距离
int d[N], s[N];  // d: 任务位置, s: 机器位置

signed main()
{
    cin >> n >> m;  // 输入任务数和机器数
    for (int i = 1; i <= n; i++)  // 输入任务位置
    {
        cin >> d[i];
    }
    for (int i = 1; i <= m; i++)  // 输入机器位置
    {
        cin >> s[i];
    }
    sort(s + 1, s + m + 1);  // 对机器位置排序
    
    for (int i = 1; i <= n; i++)  // 为每个任务分配最近的机器
    {
        int x = lower_bound(s + 1, s + m + 1, d[i]) - s;  // 找到第一个≥d[i]的机器
        int minn = 1e18;  // 初始化最小距离
        if (x <= m)  // 如果找到了≥d[i]的机器
        {
            minn = min(minn, abs(s[x] - d[i]));  // 与右侧机器比较
        }
        if (x > 1)  // 如果左侧有机器
        {
            minn = min(minn, abs(d[i] - s[x - 1]));  // 与左侧机器比较
        }
        ans += minn;  // 累加最小距离
    }
    cout << ans << endl;  // 输出最小总距离
    return 0;
}

【运行结果】

3 2
1 4 7
3 6
4

C - Chain Blackout

【题目来源】

AtCoder:C - Chain Blackout

【题目描述】

Takahashi manages the power grid of a certain region. This power grid has \(N\) substations, numbered from \(1\) to \(N\).
高桥负责管理某地区的电网。这个电网有 \(N\) 个变电站,编号从 \(1\)\(N\)

There are \(M\) transmission lines laid between substations. Transmission line \(k\) (\(1 \leq k \leq M\)) supplies power in the direction from substation \(U_k\) to substation \(V_k\). There are no self-loops (\(U_k \neq V_k\)). Also, the same ordered pair \((U_k, V_k)\) does not appear more than once. However, for two substations \(u, v\), it is possible for a transmission line from substation \(u\) to substation \(v\) and a transmission line from substation \(v\) to substation \(u\) to exist simultaneously.
变电站之间有 \(M\) 条输电线路。输电线路 \(k\)\(1 \leq k \leq M\))沿从变电站 \(U_k\) 到变电站 \(V_k\) 的方向输送电力。不存在自环(\(U_k \neq V_k\))。此外,同一个有序对 \((U_k, V_k)\) 不会出现超过一次。但是,对于两个变电站 \(u, v\),可能存在从变电站 \(u\) 到变电站 \(v\) 的输电线路和从变电站 \(v\) 到变电站 \(u\) 的输电线路同时存在。

Each substation \(i\) (\(1 \leq i \leq N\)) has a durability value \(T_i\). Also, each substation \(i\) has a non-negative integer value called its load. Initially, all substations are operational, and the load of substation \(i\) equals the number of transmission lines through which power flows into substation \(i\), that is, the number of transmission lines \(k\) satisfying \(V_k = i\) (the in-degree of substation \(i\) in the directed graph).
每个变电站 \(i\)\(1 \leq i \leq N\))有一个耐久值 \(T_i\)。此外,每个变电站 \(i\) 有一个称为负载的非负整数值。初始时,所有变电站都在运行,变电站 \(i\) 的负载等于流入变电站 \(i\) 的输电线路数量,即满足 \(V_k = i\) 的输电线路 \(k\) 的数量(有向图中变电站 \(i\) 的入度)。

In this power grid, when a substation's load exceeds its durability value, a blackout occurs, and it may spread in a chain reaction. The specific procedure is as follows.
在这个电网中,当一个变电站的负载超过其耐久值时,会发生停电,并可能以连锁反应扩散。具体过程如下。

Note that the load of a substation that has already experienced a blackout does not change afterwards.
注意已经发生过停电的变电站的负载之后不会改变

  1. Blackout occurrence: Among the substations that have not yet experienced a blackout, if there exists one whose load strictly exceeds its durability value (that is, for substation \(j\), load \(> T_j\)), choose any one of them. Let the chosen substation be substation \(s\). If no such substation exists, the chain ends.
    停电发生:在尚未发生停电的变电站中,如果存在一个变电站其负载严格大于其耐久值(即对于变电站 \(j\),负载 \(> T_j\)),则选择其中任意一个。设被选的变电站为 \(s\)。如果不存在这样的变电站,则连锁终止。
  2. Blackout processing: Substation \(s\) experiences a blackout and ceases to function. Since power transmission from substation \(s\) is cut off, each destination substation tries to compensate for the lost power through other routes, resulting in increased load. Specifically, for each transmission line \(k\) such that \(U_k = s\), if the destination substation \(V_k\) has not yet experienced a blackout, the load of substation \(V_k\) is increased by \(1\) (the load of substations that have already experienced a blackout does not change).
    停电处理:变电站 \(s\) 发生停电并停止运行。由于从变电站 \(s\) 的电力传输被切断,每个目标变电站会试图通过其他路径补偿损失的电力,导致负载增加。具体来说,对于每条满足 \(U_k = s\) 的输电线路 \(k\),如果目标变电站 \(V_k\) 尚未发生停电,则变电站 \(V_k\) 的负载增加 \(1\)(已经发生停电的变电站的负载不会改变)。
    3. 重复:返回步骤 1。
  3. Repeat: Return to step 1.
    重复:返回步骤 1。

Since the number of substations is finite, this chain always terminates in a finite number of steps.
由于变电站数量有限,这个连锁过程总是会在有限步内终止。

Note: It can be proven that regardless of which substation is chosen when multiple substations satisfy the condition in step 1, the final set of substations that experience a blackout is the same. Therefore, the answer is uniquely determined.
注意:可以证明,在步骤 1 中有多个变电站满足条件时,无论选择哪个变电站,最终发生停电的变电站集合是相同的。因此,答案是唯一确定的。

When the chain has completely settled (that is, when no substation that has not yet experienced a blackout has a load strictly exceeding its durability value), find all the substation numbers that ultimately experienced a blackout.
当连锁完全稳定后(即当所有尚未发生停电的变电站的负载都不严格大于其耐久值时),求最终发生停电的所有变电站编号。

【输入】

\(N\) \(M\)
\(T_1\) \(T_2\) \(\ldots\) \(T_N\)
\(U_1\) \(V_1\)
\(U_2\) \(V_2\)
\(\vdots\)
\(U_M\) \(V_M\)

  • The first line contains the number of substations \(N\) and the number of transmission lines \(M\), separated by a space.
  • The second line contains the durability values \(T_1, T_2, \ldots, T_N\) of each substation, separated by spaces.
  • In the following \(M\) lines, the \(k\)-th line (\(1 \leq k \leq M\)) contains \(U_k\) and \(V_k\) separated by a space, representing the information of transmission line \(k\). This means there is a transmission line supplying power from substation \(U_k\) to substation \(V_k\).

【输出】

Output the numbers of all substations that ultimately experienced a blackout, in ascending order, separated by spaces, on a single line. If no substation experienced a blackout, output -1 instead.

【输入样例】

5 5
0 1 1 1 1
1 2
1 3
2 3
3 4
4 5

【输出样例】

3 4 5

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 200005, M = N * 2;
int n, m;
int h[N], e[M], ne[M], idx;  // 邻接表
int ind[N], t[N];  // ind: 实际负载, t: 最大负载
bool vis[N];  // 标记是否停电
queue<int> q;  // BFS队列

// 添加有向边
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

int main()
{
    cin >> n >> m;  // 输入节点数和边数
    for (int i = 1; i <= n; i++)  // 输入每个节点的最大负载
    {
        cin >> t[i];
    }
    memset(h, -1, sizeof(h));
    for (int i = 1; i <= m; i++)  // 建图
    {
        int u, v;
        cin >> u >> v;
        add(u, v);
        ind[v]++;  // 初始负载
    }
    for (int i = 1; i <= n; i++)  // 初始检查
    {
        if (ind[i] > t[i])  // 如果实际负载超过最大负载
        {
            q.push(i);  // 加入队列
        }
    }
    while (!q.empty())  // BFS模拟停电传播
    {
        int u = q.front();
        q.pop();
        if (vis[u])  // 已经停电,跳过
        {
            continue;
        }
        vis[u] = 1;  // 标记停电
        for (int i = h[u]; i != -1; i = ne[i])  // 遍历邻居
        {
            int v = e[i];
            if (vis[v])  // 邻居已停电
            {
                continue;
            }
            ind[v]++;  // 邻居负载增加(因为u停电,电流集中到邻居)
            if (ind[v] > t[v])  // 如果邻居过载
            {
                q.push(v);  // 加入队列
            }
        }
    }
    bool flag = false;  // 标记是否有节点停电
    for (int i = 1; i <= n; i++)  // 输出停电的节点
    {
        if (vis[i])
        {
            cout << i << " ";
            flag = true;
        }
    }
    if (flag)  // 如果有停电节点
    {
        cout << endl;
    }
    else
    {
        cout << -1 << endl;  // 没有停电节点
    }
    return 0;
}

【运行结果】

5 5
0 1 1 1 1
1 2
1 3
2 3
3 4
4 5
3 4 5
posted @ 2026-04-01 21:18  团爸讲算法  阅读(2)  评论(0)    收藏  举报