You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Kruskal算法实现仅首尾插节点的TSP及End(u)/End(v)功能

针对该变种Kruskal实现TSP的End函数实现方案

你用到的是仅允许在路径头尾拼接的Kruskal变种TSP算法,本质是生成一条总权值最小的哈密顿路径,所有节点度数最大为2,无分支和环。
其中End(u)函数的核心作用是:判断节点u是否为其所在路径段的端点,仅端点允许参与拼接,否则会出现度数>2的分支节点。


实现思路

普通并查集仅能判断节点是否连通,无法识别端点,因此需要新增度数数组记录每个节点的连接度数:

  • 初始状态下每个节点独立为一个路径段,度数为0,自身就是端点
  • 路径中间节点的度数为2,不可再参与拼接
  • 路径头尾端点的度数为1(单节点路径度数为0),可参与拼接

End(u)的判断逻辑等价于deg[u] < 2,只要满足该条件,u就是所在路径段的可用端点。


现有代码改造方案

1. 新增类成员变量

在Graph类的私有成员中新增度数数组,记录每个节点的连接度数:

private:
  vector<pair<int, edge> > G;  // 原始图边集
  vector<pair<int, edge> > T;  // 生成的TSP路径边集
  int *parent;
  int *deg; // 节点度数数组
  int V;  // 总节点数

2. 初始化度数数组

修改构造函数,初始化新增的度数数组:

Graph::Graph(int V) {
  parent = new int[V];
  deg = new int[V];
  for (int i = 0; i < V; i++) {
    parent[i] = i;
    deg[i] = 0; // 初始单节点路径度数为0,自身为端点
  }
  G.clear();
  T.clear();
}

3. 修改Kruskal主逻辑

在原有连通性判断前,新增端点校验,符合要求才将边加入路径:

void Graph::kruskal() {
  int i, u, v, uRep, vRep;
  sort(G.begin(), G.end()); // 按边权升序排序
  // 哈密顿路径共V个节点,只需V-1条边,凑够即可提前退出
  for (i = 0; i < G.size() && T.size() < V - 1; i++) {
    u = G[i].second.first;
    v = G[i].second.second;
    // 非端点节点跳过,避免生成度数大于2的节点
    if (deg[u] >= 2 || deg[v] >= 2) continue;
    uRep = find_set(u);
    vRep = find_set(v);
    // 不在同一连通分量,避免成环
    if (uRep != vRep) {
      T.push_back(G[i]);
      union_set(uRep, vRep);
      // 拼接后两个端点度数各加1
      deg[u]++;
      deg[v]++;
    }
  }
}

内容的提问来源于stack exchange,提问作者bilal walker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:15:09