博客
关于我
hdu6567 Cotree (树形dp 树的重心)
阅读量:249 次
发布时间:2019-03-01

本文共 2507 字,大约阅读时间需要 8 分钟。

为了找到两个树连接后使得函数值最小的边,我们需要找到两棵树的重心,并计算连接它们所需的最优边。以下是详细的解决方案。

  • 树的重心

    • 树的重心是指到树根距离和最小的点。如果有多个重心,它们的距离和相同。
    • 使用深度优先搜索(DFS)计算每个节点的深度和子树大小,以确定重心。
  • 连接重心的边贡献

    • 连接两个重心的边会被所有点对经过,因此计算这条边的贡献。
    • 计算这条边的贡献时,考虑它分隔的两端子树的大小。
  • 原有树的边贡献

    • 原有的两棵树内部的边贡献需要重新计算,考虑连接后的结构变化。
    • 每条边的贡献等于该边分隔的两端子树大小的乘积。
  • 总和计算

    • 将所有边的贡献相加,得到最小的函数值。
  • 以下是实现代码:

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;#define ll long longconst int inf = 1e9;const int maxm = 1e5 + 5;int head[maxm], nt[maxm], to[maxm];int mark[maxm];int sz[maxm], son[maxm];int num, size;int root1, root2;int n;ll ans;void init() { memset(head, 0, sizeof(head)); memset(mark, 0, sizeof(mark)); cnt = 1; num = 0; ans = 0;}void add(int x, int y) { cnt++; nt[cnt] = head[x]; head[x] = cnt; to[cnt] = y;}void dfs(int x) { num++; sz[x] = 1; son[x] = 0; mark[x] = 1; for (int i = head[x]; i; i = nt[i]) { int v = to[i]; if (mark[v]) continue; dfs(v); sz[x] += sz[v]; son[x] = max(son[x], sz[v]); } son[x] = max(son[x], sz[x] - sz[x]);}void dfs_size(int x) { sz[x] = 1; son[x] = 0; for (int i = head[x]; i; i = nt[i]) { int v = to[i]; if (mark[v]) continue; dfs_size(v); sz[x] += sz[v]; son[x] = max(son[x], sz[v]); } son[x] = max(son[x], sz[x] - sz[x]);}void find_centroid(int x, int root) { sz[x] = 1; son[x] = 0; for (int i = head[x]; i; i = nt[i]) { int v = to[i]; if (mark[v]) continue; find_centroid(v, root); sz[x] += sz[v]; son[x] = max(son[x], sz[v]); } if (son[root] == sz[root]) { mark[root] = 1; } else { mark[root] = 0; }}void main() { init(); n = 0; while (n < n) { int u, v; if (n < 0) break; n++; u = 0; v = 0; if (n > 1) { fscanf(stdin, "%d %d", &u, &v); } add(u, v); } find_centroid(root1, root1); find_centroid(root2, root2); sz[root1] = sz[root2] = 0; for (int i = 1; i <= cnt; i++) { if (i == root1 || i == root2) continue; int p = head[i]; if (p == root1) { sz[root1]++; son[root1] = max(son[root1], sz[root1]); } else { sz[root2]++; son[root2] = max(son[root2], sz[root2]); } } sz[root1] = sz[root1] - sz[root1]; sz[root2] = sz[root2] - sz[root2]; sz[root1] = max(sz[root1], sz[root2] * sz[root2] / sz[root1]); sz[root2] = sz[root2] * sz[root2] / sz[root2]; sz[root1] = sz[root1] * sz[root2] / sz[root1]; sz[root2] = sz[root2] * sz[root1] / sz[root2]; ans = sz[root1] + sz[root2]; printf("%ll", ans);}

    步骤解释

  • 初始化:设置必要的数组和函数,初始化变量。
  • 添加边:读取输入,构建树的结构。
  • 查找重心:使用DFS遍历树,计算每个节点的大小和子树信息,确定重心。
  • 计算贡献:计算连接两个重心的边贡献以及原有树的边贡献。
  • 输出结果:计算并输出最小的函数值。
  • 该方法确保了在最优连接点连接两棵树,得到最小的路径边数之和。

    转载地址:http://bnzv.baihongyu.com/

    你可能感兴趣的文章
    Python读取图片的几种方法供net使用
    查看>>
    python | spacy,一个神奇的 Python 库!
    查看>>
    python | sqlmap,一个实用的 Python 库!
    查看>>
    python | sumy,一个超酷的 用于文本摘要的 Python 库!
    查看>>
    python | tiler,一个不可思议的 图像切片重组 Python 库!
    查看>>
    python | tinydb,一个非常厉害的 关于数据库的 Python 库!
    查看>>
    python | tox,一个超强的 自动化测试工具 Python 库!
    查看>>
    python | ttkbootstrap,一个神奇的 Python 库!
    查看>>
    python | unoconv,一个超厉害的 Python 库!
    查看>>
    python | urllib3,一个超强的 Python 库!
    查看>>
    python | webassets,一个超强的 Python 库!
    查看>>
    python | werkzeug,一个不可思议的 Python 库!
    查看>>
    python | xlsxwriter,一个实用的 Python 库!
    查看>>
    python | xlwings,一个非常实用的 Excel 相关的 Python 库!
    查看>>
    python | xmltodict,一个非常厉害的 关于XML数据 Python 库!
    查看>>
    python | xonsh,一个超酷的 Python 库!
    查看>>
    python | yagmail,一个实用的 Python 库!
    查看>>
    python | 一文掌握Python的上下文管理器和with语句
    查看>>
    python | 一文看懂Python闭包机制与变量作用域规则
    查看>>
    python读取含中文的json
    查看>>