博客
关于我
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/

    你可能感兴趣的文章
    Pinia:$subscribe()的使用场景
    查看>>
    Pinpoint对Kubernetes关键业务模块进行全链路监控
    查看>>
    Pinterest 大规模缓存集群的架构剖析
    查看>>
    pintos project (2) Project 1 Thread -Mission 1 Code
    查看>>
    PinYin4j库的使用
    查看>>
    PIP
    查看>>
    pip install goose-extractor // SyntaxError: Missing parentheses in call to 'print'
    查看>>
    pip install mysqlclient报错
    查看>>
    pip install 出现报asciii码错误的解决
    查看>>
    pip throws TypeError: parse() got an unexpected keyword argument ‘transport_encoding‘ 在尝试安装新软件包时
    查看>>
    pip 下载慢
    查看>>
    pip 升级报错AttributeError: ‘NoneType’ object has no attribute ‘bytes’
    查看>>
    pip 安装opencv-python卡死
    查看>>
    pip 安装出现异常
    查看>>
    Pip 安装失败:需要 SSL
    查看>>
    Pip 安装挂起
    查看>>
    pip 或 pip3 为 Python 3 安装包?
    查看>>
    pip 文件损坏导致 pip无法使用 报错 ImportError: cannot import name 'main' from 'pip._int
    查看>>
    pip 无法从 requirements.txt 安装软件包
    查看>>
    pip/pip3更换国内源
    查看>>