• C. Link Cut Centroids(树的重心性质)


    题意:

    对于一棵树 删除一条边再加上一条边使得新树只有一个重心

    输入
    输入由多个测试案例组成。第一行包含一个整数t(1≤t≤104)--测试案例的数量。测试用例的描述如下。

    每个测试用例的第一行包含一个整数n(3≤n≤105)--顶点的数量。

    接下来的n-1行中的每一行都包含两个整数x,y(1≤x,y≤n)。这意味着,存在一条连接顶点x和y的边。

    可以保证给定的图是一棵树。

    保证所有测试案例的n之和不超过105。

    输出
    对于每个测试案例,打印两行。

    在第一行打印两个整数x1,y1(1≤x1,y1≤n),这意味着你切断了顶点x1和y1之间的边。应该存在连接顶点x1和y1的边。

    在第二行打印两个整数x2,y2(1≤x2,y2≤n),这意味着你增加了顶点x2和y2之间的边。

    这两次操作后的图形应该是一棵树。

    如果有多个解决方案,你可以打印任何一个。

    树的重心:只有当你切掉这个顶点(移除它并移除这个顶点的所有边)时,剩余图形的最大连接部分的大小才是最小的。

    树的重心的一些性质:
    1.删除重心后的所有子树,节点树都不超过原树的一半。
    2.一颗树最多两个重心,而且相邻。
    3.树中所有的节点到重心的距离之和最小,要是有两个重心,那么他们的距离相等。
    4.这颗树要是删除或者增加一条边,重心最多只移动一条边。

    题解:

    分情况讨论
    1.对于树如果是只有一个重心,那么随便取一个与他直连的点,断开然后再连接即可

    2.如果有两个重心,根据重心的性质我们可以知道,这两个x,y重心必定相邻,那么我们就取其中一个重心x,找到其他与他直连的点z并且这个点和另一个重心y不相连,然后断开x与z,连接z与y即可

    1. #include<iostream>
    2. #include<algorithm>
    3. #include<map>
    4. #include<queue>
    5. #include<vector>
    6. #include<cstring>
    7. using namespace std;
    8. int vis[100050];
    9. vector<int> p[100050];
    10. int son[100060];
    11. int res = 0;
    12. int n;
    13. int t1 = 0,t2 = 0;
    14. int ans = 0;
    15. int dfs(int u)
    16. {
    17. vis[u] = 1;
    18. int sum = 1,res = 0;
    19. for(int i = 0;i < p[u].size();i++)
    20. {
    21. int j = p[u][i];
    22. if(!vis[j])
    23. {
    24. int s = dfs(j);
    25. sum += s;
    26. res = max(s,res);
    27. }
    28. }
    29. res = max(res,n - sum);
    30. if(ans >= res)
    31. {
    32. son[u] = res;
    33. t2 = t1;
    34. t1 = u;
    35. ans = res;
    36. }
    37. return sum;
    38. }
    39. void solve()
    40. {
    41. cin >> n;
    42. for(int i = 1;i <= n;i++)
    43. p[i].clear(),vis[i] = 0,son[i] = 0;
    44. res = 0; ans = 1e9;
    45. t1 = 0,t2 = 0;
    46. for(int i = 1;i < n;i++)
    47. {
    48. int l,r;
    49. cin >> l >>r;
    50. p[l].push_back(r);
    51. p[r].push_back(l);
    52. }
    53. dfs(1);
    54. if(son[t1] != son[t2])
    55. {
    56. cout<<t1<<" "<<p[t1][0]<<"\n";
    57. cout<<t1<<" "<<p[t1][0]<<"\n";
    58. }
    59. else
    60. {
    61. int u = 0;
    62. for(int i = 0;i < p[t1].size();i++)
    63. {
    64. int j = p[t1][i];
    65. if(j!=t2)
    66. {
    67. u = j;
    68. break;
    69. }
    70. }
    71. cout<<t1<<" "<<u<<"\n";
    72. cout<<t2<<" "<<u<<"\n";
    73. }
    74. }
    75. int main()
    76. {
    77. int t = 1;
    78. cin >> t;
    79. while(t--)
    80. {
    81. solve();
    82. }
    83. }
    84. //
    85. //

  • 相关阅读:
    HTML5期末考核大作业——学生网页设计作业源码HTML+CSS+JavaScript 中华美德6页面带音乐文化
    mysql5.7.44误删除数据后,使用binlog日志恢复
    Yolov8小目标检测(19):动态蛇形卷积(Dynamic Snake Convolution),增强细长微弱特征 | ICCV2023
    英伟达再放AI芯片“大招” H200 GPU是人工智能技术的里程碑
    自动化您的Instagram帐户的程序InstaBot Pro 7.0.2
    深入了解汽车级功率MOSFET NVMFS2D3P04M8LT1G P沟道数据表
    openjudge 1.8.5 计算鞍点
    Gartner研究:在中国,混合云的采用已成为主流趋势
    Redis 中使用 list,streams,pub/sub 几种方式实现消息队列
    Hadoop:HDFS--分布式文件存储系统
  • 原文地址:https://blog.csdn.net/m0_64158084/article/details/127868681