本文共 2507 字,大约阅读时间需要 8 分钟。
为了找到两个树连接后使得函数值最小的边,我们需要找到两棵树的重心,并计算连接它们所需的最优边。以下是详细的解决方案。
树的重心:
连接重心的边贡献:
原有树的边贡献:
总和计算:
以下是实现代码:
#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);}
该方法确保了在最优连接点连接两棵树,得到最小的路径边数之和。
转载地址:http://bnzv.baihongyu.com/