C++ 算法考级专栏
真题分析、矩阵探测、递归回溯与基础语法
🎨 视觉封面【图论·全源可达性与割点检测】GESP七级 / CSP-S 题解:luogu-P17459 [GESP202609 七级] 必经之路
CCF GESP 2026年9月认证(第十五次认证)C++ 七级试题,洛谷 P17459。本题严格遵循 CCF GESP 官方大纲规范,重点考察图论·全源可达性与割点检测。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。
P17459 [luogu-P17459 [GESP202609 七级] 必经之路]
🔗 洛谷原题传送门:P17459
题目要求
题目描述
有向图 ( 结点 边)。入度为 0 的点为合法起点,出度为 0 的点为合法终点。 若所有可能的从合法起点到合法终点的路径都必经过结点 ,则称 为必经点。 求 中所有必经点的编号(从小到大输出)。
输入格式
第一行两个正整数 。 接下来 行每行两个正整数 。
输出格式
第一行输出必经点数量 ;第二行输出所有必经点编号(空格隔开)。若 则不输出第二行。
输入输出样例
样例输入 #1
8 9
1 3
2 3
3 4
4 5
5 6
6 7
6 8
2 4
5 7
样例输出 #1
2
4 5
说明/提示
。
题目分析与解题思路
- 必经点的充要条件: 结点 是必经点 在图 中删去结点 后,不存在任何一条从某个合法起点到某个合法终点的路径。
- 高效暴力检验算法:
由于数据范围较小(),我们可以针对每个待选结点 单独测试:
- 将所有起点 入队,在无结点 的残留图上执行多源 BFS/DFS;
- 若遍历过程中访问到了任何一个终点 ,说明存在避开 的路径,故 不是必经点;
- 若遍历结束未访问到任何合法终点,则证明所有合法路径都依赖 ,因此 是必经点!
- 复杂度分析: 单次 BFS 耗时 ,枚举 个点总耗时 次操作,耗时约 ,极度稳健。
完整参考代码 (C++11)
/**
* Problem: luogu-P17459
* Standard: C++11 (CCF GESP 官方大纲规范)
* Author: OneCoder
*/
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<vector<int>> adj(n + 1);
vector<int> in_deg(n + 1, 0);
vector<int> out_deg(n + 1, 0);
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
out_deg[u]++;
in_deg[v]++;
}
vector<int> starts;
vector<bool> is_end(n + 1, false);
for (int i = 1; i <= n; ++i) {
if (in_deg[i] == 0) starts.push_back(i);
if (out_deg[i] == 0) is_end[i] = true;
}
vector<int> must_pass;
// 逐个检验结点 u 是否为必经点
for (int u = 1; u <= n; ++u) {
queue<int> q;
vector<bool> visited(n + 1, false);
for (int s : starts) {
if (s != u) {
visited[s] = true;
q.push(s);
}
}
bool can_reach_end = false;
while (!q.empty()) {
int curr = q.front();
q.pop();
if (is_end[curr] && curr != u) {
can_reach_end = true;
break;
}
for (int nxt : adj[curr]) {
if (nxt != u && !visited[nxt]) {
visited[nxt] = true;
q.push(nxt);
}
}
}
if (!can_reach_end) {
must_pass.push_back(u);
}
}
cout << must_pass.size() << "\n";
if (!must_pass.empty()) {
for (size_t i = 0; i < must_pass.size(); ++i) {
cout << must_pass[i] << (i + 1 == must_pass.size() ? "" : " ");
}
cout << "\n";
}
return 0;
}
考点归纳与备考建议
- 考纲匹配度:严格对标 CCF GESP 七级考纲重点,绝不超纲,注重基础算法与逻辑建模规范;
- 规范防范:所有代码严格以 C++11 标准编译运行,针对整数溢出、边界判断、空状态均做了详尽严整的防御性处理。
所有代码开源上传至 GitHub:yummy-code 仓库 · GESP 专题站:GESP WIKI
欢迎加入:C++ GESP/CSP 考级答疑群(688906745) 与 Java/Python交流群(982860385),点击可直接加群。
猜你想读 · 相关文章推荐
【括号序列平衡度与子序列计数DP】GESP七级 / CSP-S 题解:luogu-P17460 [GESP202609 七级] 括号序列
CCF GESP 2026年9月认证(第十五次认证)C++ 七级试题,洛谷 P17460。本题严格遵循 CCF GESP 官方大纲规范,重点考察括号序列平衡度与子序列计数DP。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。
【GESP】C++七级考试大纲知识点梳理 (3) 图论基础与遍历算法
GESP C++七级考试大纲的第 3 条考点正式引入了图论 (Graph Theory)。图论是计算机科学中极其重要的数据结构,用来解决大量的“关系”问题(如地图导航、社交网络)。七级要求掌握图的基本概念、存储方式以及最核心的两种遍历算法:DFS 和 BFS。 (3)图的定义及及基本图论算法。包括图的定义、图的种类(有...
【仙人掌图性质与乘法原理生成树计数】GESP八级 / CSP-S 题解:luogu-P17461 [GESP202609 八级] 生成树计数
CCF GESP 2026年9月认证(第十五次认证)C++ 八级试题,洛谷 P17461。本题严格遵循 CCF GESP 官方大纲规范,重点考察仙人掌图性质与乘法原理生成树计数。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。
OneCoder (lihongzheshuai)
一个中年人的自留地,记录学习 C++、GESP/NOI、Java、Python 与算法架构的心得体会。本站唯一网址:coderli.com