传球游戏【思维】

传球游戏

难度:简单

知识点:图论、度数统计、无向图

时间复杂度: O(n + m)

空间复杂度: O(n)

一、题目描述

小明正在和朋友们一起玩传球游戏。

游戏可以抽象成一个包含 n 个节点、m 条边的无向图,每个人恰好占据一个节点。

每条边都有一个边权 w,表示两个节点之间的距离。

传球需要遵守以下规则:

  1. 每个人只能将球传给与自己直接相连,且距离不超过 k 的人。
  2. 除第一个人外,每个人都不能将球传回给刚刚传球给自己的人。
  3. 当某个人无法继续传球时,游戏结束。

现在,假设球最开始可以交给任意一个人,求:

  • 游戏最终可能在哪些节点结束?
  • 这些节点共有多少个?

输出所有可能结束游戏的节点编号,按照从小到大的顺序排列。

二、输入格式

第一行输入三个整数:

text 复制代码
n m k

分别表示:

  • n:节点数量
  • m:边的数量
  • k:传球的最大距离限制

接下来 m 行,每行输入三个整数:

text 复制代码
u v w

表示节点 u 和节点 v 之间存在一条权值为 w 的无向边。

数据范围:

  • 1≤n,m≤1061 \le n,m \le 10^61≤n,m≤106
  • 1≤k,w≤1091 \le k,w \le 10^91≤k,w≤109
  • 保证图中没有重边和自环。

三、输出格式

第一行输出一个整数,表示所有可能成为游戏终点的节点数量。

第二行按照从小到大的顺序输出这些节点的编号,编号之间用空格分隔。

四、样例

样例输入

text 复制代码
4 3 4
1 2 3
1 3 5
2 3 4

样例输出

text 复制代码
3
1 3 4

样例解释

由于限制 k=4k=4k=4,只有边权不超过 4 的边可以传球。

因此:

  • 边 1 <-> 2,权值为 3,可以传球。
  • 边 1 <-> 3,权值为 5,不能传球。
  • 边 2 <-> 3,权值为 4,可以传球。
  • 节点 4 没有任何边,无法传球。

筛选后的有效图如下:

text 复制代码
1 ----- 2 ----- 3

          4

此时:

  • 节点 1 的有效度数为 1。
  • 节点 2 的有效度数为 2。
  • 节点 3 的有效度数为 1。
  • 节点 4 的有效度数为 0。

节点 1 和 3 只有一个可以传球的邻居,如果球从这个邻居传过来,就无法继续传球。

节点 4 没有任何可以传球的邻居,游戏可以直接在该节点结束。

节点 2 有两个可以传球的邻居,无论从哪个邻居接球,都可以继续传给另一个邻居。

因此答案为:

text 复制代码
1 3 4

共 3 个节点。

五、解题思路

1. 核心思想

统计每个节点的有效度数。

在无向图中,节点的度数表示与该节点相连的边的数量。

但本题有一个特殊限制:

只有边权满足

w≤k w \le k w≤k

的边才能用于传球。

因此,我们只需要统计满足条件的边所形成的图中,每个节点的度数。

定义:

degi degi degi

表示节点 i 的有效度数。

2. 分类讨论

对于任意节点 i,根据有效度数可以分为三种情况。

情况一:degi=0degi=0degi=0

该节点没有任何可以传球的邻居。

如果游戏从该节点开始,就无法继续传球。

因此,该节点可以成为游戏终点。

情况二:degi=1degi=1degi=1

该节点只有一个可以传球的邻居。

如果球从这个唯一的邻居传过来,由于不能将球传回给刚刚传球的人,因此无法继续传球。

所以,该节点也可以成为游戏终点。

情况三:degi≥2degi\ge 2degi≥2

该节点至少有两个可以传球的邻居。

当球从某个邻居传过来时,即使不能将球传回原来的节点,仍然至少存在另一个邻居可以接球。

因此,该节点不可能成为游戏终点。

3. 得出结论

一个节点能够成为游戏终点,当且仅当:

degi≤1 \boxed{degi\le 1} degi≤1

因此,我们只需要:

  1. 遍历所有边。
  2. 如果边权 w <= k,则将两个端点的有效度数加一。
  3. 遍历所有节点,找出有效度数小于等于 1 的节点。
  4. 按照编号从小到大的顺序输出结果。

注意:本题不需要 BFS 或 DFS,只需要统计度数即可。

六、C++ 代码(ACM 模式)

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    long long k;
    cin >> n >> m >> k;

    // 统计每个节点的有效度数
    vector<int> deg(n + 1, 0);

    // 读入所有边
    for (int i = 0; i < m; i++) {
        int u, v;
        long long w;
        cin >> u >> v >> w;

        // 只有边权不超过 k 的边才能传球
        if (w <= k) {
            deg[u]++;
            deg[v]++;
        }
    }

    vector<int> ans;

    // 找到所有可能成为游戏终点的节点
    for (int i = 1; i <= n; i++) {
        if (deg[i] <= 1) {
            ans.push_back(i);
        }
    }

    // 输出终点数量
    cout << ans.size() << '\n';

    // 按照编号从小到大输出
    for (int i = 0; i < (int)ans.size(); i++) {
        if (i > 0) cout << ' ';
        cout << ans[i];
    }

    cout << '\n';

    return 0;
}

七、复杂度分析

设图中有 n 个节点、m 条边。

时间复杂度

  1. 遍历 m 条边,统计有效度数,时间复杂度为 O(m)O(m)O(m)。
  2. 遍历 n 个节点,筛选答案,时间复杂度为 O(n)O(n)O(n)。
  3. 输出答案,最坏需要 O(n)O(n)O(n) 的时间。

因此,总时间复杂度为:

O(n+m) \boxed{O(n+m)} O(n+m)

空间复杂度

算法使用:

  • 长度为 n + 1 的度数数组 deg,空间复杂度为 O(n)O(n)O(n)。
  • 最多存储 n 个答案的数组 ans,空间复杂度为 O(n)O(n)O(n)。

因此,总空间复杂度为:

O(n) \boxed{O(n)} O(n)

无需存储邻接表,也无需额外排序,因为我们已经按照编号从小到大遍历节点。

八、总结

这道题的关键在于将传球规则转化为图论中的度数条件。

虽然题目描述的是一个不断传球的过程,但实际上并不需要模拟过程,也不需要搜索每个起点。

只需要筛选满足 w≤kw\le kw≤k 的边,并统计每个节点的有效度数。

最终找出满足:

degi=0或degi=1 \boxed{degi=0 \quad \text{或} \quad degi=1} degi=0或degi=1

的所有节点即可。

核心结论:

在满足边权限制的无向图中,所有有效度数不超过 1 的节点,都是可能的游戏终点。

这是一道典型的 图论建模 + 度数统计 题目。

相关推荐
FL16238631292 小时前
关于2026年南昌大学811信号与系统最后一题电路系统解题思路
算法
殷色玫瑰2 小时前
C++ STL:map 与 set 详解——从底层红黑树到实际应用
c语言·数据结构·c++·算法·visualstudio·rpc
行者全栈架构师2 小时前
【鸿蒙心迹】鸿蒙网络请求架构实战——@ohos.net.http 到 Axios 封装、拦截器与统一错误处理(HarmonyOS 7.x)
前端·算法·架构
小宋10212 小时前
OpenTelemetry GenAI可观测性实战:串起模型、工具、Token与错误
java·人工智能·算法·贪心算法
嫂子开门我是_我哥3 小时前
青少年抑郁、焦虑、失眠与自杀相关表现的症状联系:一篇网络分析论文所使用的算法深度解读
论文阅读·算法·论文笔记
渊鱼L3 小时前
CAD随机颗粒插件2D V2.0 更新说明
算法
Lazionr3 小时前
unordered_map和unordered_set的使用
开发语言·c++·算法
行者全栈架构师3 小时前
从 55% 到 6%:一个快餐营养规划器的算法迭代实录
后端·算法·架构
Laurie三省3 小时前
现场版却配上录音室版的歌词?聊聊我给开源 Mac 歌词软件写的多源打分算法
算法·macos·go