博客
关于我
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函数定义的基本格式_零基础学python-2.19 定义函数、调用函数与默认参数
    查看>>
    Python+Selenium之数据驱动测试的实现
    查看>>
    python函数定义与使用+返回值简解
    查看>>
    Python+Selenium登录
    查看>>
    Python日期时间模块
    查看>>
    Python函数合集:足足68个内置函数请收好!
    查看>>
    Python+Selenium自动化测试项目实战
    查看>>
    Python+Selenium自动化测试项目实战【建议收藏】
    查看>>
    Python+Selenium自动化测试:Page Object模式
    查看>>
    python+selenium进行cnblog的自动化登录测试
    查看>>
    Python函数只返回第一个值而不是数据框
    查看>>
    Python+SQL实战:京东用户行为数据分析案例解析(上)
    查看>>
    Python+SQL实战:京东用户行为数据分析案例解析(下)
    查看>>
    PYTHON+Twisted+sqlanydb=ABORT()
    查看>>
    Python函数之返回值、作用域和局部变量
    查看>>
    Python+统计学 | 探索常用的数据分析统计分布
    查看>>
    python, selenium中用于切换帧的函数
    查看>>
    python函数
    查看>>
    python----线程、进程、协程的区别及多线程详解
    查看>>
    python---5
    查看>>