找回密码
 立即注册
查看: 35|回复: 6

[已经解决] 求总权重结果不正确

[复制链接]
发表于 2026-10-17 22:07:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

×
如题,可运行,但是结果一直是10
正确的应该是x出现两次后被两个父节点共享,应该是20
但是一直找不到原因........

  1. #include <iostream>
  2. #include <vector>
  3. #include <memory>
  4. #include <functional>
  5. #include <unordered_map>
  6. #include <string>
  7. #include <algorithm>

  8. template<typename T>
  9. class Registry {
  10.     std::unordered_map<std::string, std::function<T(const std::vector<std::string>&)>> creators;
  11. public:
  12.     void add(const std::string& key, std::function<T(const std::vector<std::string>&)> fn) {
  13.         creators[key] = fn;
  14.     }
  15.     T create(const std::string& key, const std::vector<std::string>& args) {
  16.         auto it = creators.find(key);
  17.         if (it == creators.end()) throw std::runtime_error("not found: " + key);
  18.         return it->second(args);
  19.     }
  20. };

  21. struct Node {
  22.     std::string name;
  23.     std::vector<std::shared_ptr<Node>> children;
  24.     int weight;
  25.     Node(std::string n, int w) : name(std::move(n)), weight(w) {}
  26. };

  27. class Builder {
  28.     Registry<std::shared_ptr<Node>> reg;
  29.     std::unordered_map<std::string, std::shared_ptr<Node>> pool;
  30. public:
  31.     Builder() {
  32.         reg.add("leaf", [](const std::vector<std::string>& a) {
  33.             return std::make_shared<Node>(a[0], std::stoi(a[1]));
  34.         });
  35.         reg.add("group", [](const std::vector<std::string>& a) {
  36.             return std::make_shared<Node>(a[0], 0);
  37.         });
  38.     }
  39.     std::shared_ptr<Node> make(const std::string& type, const std::vector<std::string>& args) {
  40.         auto n = reg.create(type, args);
  41.         pool[n->name] = n;
  42.         return n;
  43.     }
  44.     std::shared_ptr<Node> get(const std::string& name) {
  45.         auto it = pool.find(name);
  46.         return it == pool.end() ? nullptr : it->second;
  47.     }
  48.     void link(const std::string& parent, const std::string& child) {
  49.         auto p = get(parent);
  50.         auto c = get(child);
  51.         if (p && c) p->children.push_back(c);
  52.     }
  53. };

  54. int computeWeight(const std::shared_ptr<Node>& node, std::vector<std::string>& visited) {
  55.     if (!node) return 0;
  56.     if (std::find(visited.begin(), visited.end(), node->name) != visited.end())
  57.         return 0;
  58.     visited.push_back(node->name);
  59.     int total = node->weight;
  60.     for (auto& c : node->children) {
  61.         total += computeWeight(c, visited);
  62.     }
  63.     return total;
  64. }

  65. int main() {
  66.     Builder b;
  67.     b.make("leaf", {"x", "10"});
  68.     b.make("group", {"left", "0"});
  69.     b.make("group", {"right", "0"});
  70.     b.make("group", {"root", "0"});
  71.     b.link("root", "left");
  72.     b.link("root", "right");
  73.     b.link("left", "x");
  74.     b.link("right", "x");

  75.     std::vector<std::string> visited;
  76.     auto root = b.get("root");
  77.     int result = computeWeight(root, visited);

  78.     std::cout << result << std::endl;
  79.     return 0;
  80. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2026-10-17 22:07:24 | 显示全部楼层
原因很明确:你的 visited 是“全局累积”的,不是“当前路径”。

遍历完 left 分支后,x 已经留在 visited 里了;等遍历 right 分支再遇到 x 时,就直接返回 0,所以只算了 10。

visited 的本意应该是防止“环”导致无限递归,所以它只需要记录**当前递归路径上**的节点。递归返回前把它弹出来(回溯)即可:


  1. int computeWeight(const std::shared_ptr<Node>& node, std::vector<std::string>& path) {
  2.     if (!node) return 0;
  3.     // 只有出现在“当前路径”上,才说明成环
  4.     if (std::find(path.begin(), path.end(), node->name) != path.end())
  5.         return 0;

  6.     path.push_back(node->name);
  7.     int total = node->weight;
  8.     for (auto& c : node->children) {
  9.         total += computeWeight(c, path);
  10.     }
  11.     path.pop_back();   // 关键:离开该节点时移除,允许别的分支再次访问
  12.     return total;
  13. }
复制代码


这样 x 会在 left 路径里算一次、在 right 路径里再算一次,结果就是 20;而真正成环时依然会被截断。

补充一点:用 name 判环有个隐患——不同节点同名会误判。更严谨的写法是按节点地址判断,比如把 path 换成 std::vector<const Node*>&,比较 node.get()。另外你贴的代码里 pool = n 应该是 pool[key] = n,std::function 的模板参数和 make_shared 的参数也被论坛吞掉了一些,注意别照抄。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2026-10-18 21:02:20 | 显示全部楼层
啊 bro真的是编程追风梦吗??
老乡见老乡 两眼泪汪汪 qaq
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

 楼主| 发表于 2026-10-19 18:14:46 | 显示全部楼层
青出于蓝 发表于 2026-10-18 21:02
啊 bro真的是编程追风梦吗??
老乡见老乡 两眼泪汪汪 qaq

是的呀,追风梦被c++难哭了走头无路想起来还有鱼C这个网站
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2026-10-19 21:52:58 | 显示全部楼层
编程追风梦小号 发表于 2026-10-19 18:14
是的呀,追风梦被c++难哭了走头无路想起来还有鱼C这个网站

我都是先想起来deepseek
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2026-10-19 21:53:09 | 显示全部楼层
编程追风梦小号 发表于 2026-10-19 18:14
是的呀,追风梦被c++难哭了走头无路想起来还有鱼C这个网站

你们是不是都不知道deepseek
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

 楼主| 发表于 2026-10-20 19:33:33 | 显示全部楼层
青出于蓝 发表于 2026-10-19 21:53
你们是不是都不知道deepseek

其实知道的哈哈哈但是都用chatgpt
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|鱼C工作室 ( 粤ICP备18085999号-1 )

GMT+8, 2026-11-5 16:09

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表