• 【蓝桥杯】砍树(树上差分)


    考察知识点:树上差分

    问题描述

            给定一棵由 n 个节点组成的树以及 m 个不重复的无序数对(a1,b1)(a2,b2) (a3,b3)......(am,bm),其中ai互不相同,bi互不相同。ai,bi(1 <= i,j <= m)。小明想知道是否能够选择一条树上的边砍断,使得对于每个(ai,bi)满足ai,bi不连通,如果可以则输出应该断掉的边的编号(编号按输入顺序从一开始),否则输出 -1。

    输入格式

    输入n + m行,第一行为两个正整数n,m。后面n - 1行,每行两个整数xi,yi表示第i条边的两个端点。后面m行,每行两个正整数ai,bi。

    输出格式

    一行一个整数,表示答案,如果有多个答案,输出编号最大的一个。

    思路

    1、按顺序输入每条边(无向边),使用邻接表储存图。

    2、使用dfs方法确定每个点所处的层次,0处于第0层,以1为根节点,处于第1层。

    3、输入每个数对a,b,d[a] ++,d[b] ++,求出点a与点b最近的公共祖先节点p,d[p] -= 2;

    4、使用深度遍历每个点,求出每条边当前的权值,如果等于m则表示这条边可以砍掉,如果边的编号大于ans,则使用ans保存。

    5、输出答案。

    代码

    1. #include
    2. using namespace std;
    3. const int N = 101000, M = 2 * N;
    4. int n,m;
    5. int h[N],e[M],ne[M],idx;
    6. int depth[N],fa[N][25];
    7. int d[N];
    8. int q[N];
    9. int ans;
    10. void add(int a,int b)
    11. {
    12. e[idx] = b,ne[idx] = h[a], h[a] = idx ++;
    13. }
    14. void bfs()
    15. {
    16. memset(depth,0x3f,sizeof depth);
    17. depth[0] = 0;
    18. depth[1] = 1;
    19. queue<int> q;
    20. q.push(1);
    21. while(!q.empty())
    22. {
    23. int t = q.front();
    24. q.pop();
    25. for(int i = h[t]; ~i; i = ne[i])
    26. {
    27. int j = e[i];
    28. if(depth[j] > depth[t] + 1)
    29. {
    30. depth[j] = depth[t] + 1;
    31. q.push(j);
    32. fa[j][0] = t;
    33. for(int k = 1; k <= 16; k ++)
    34. fa[j][k] = fa[fa[j][k - 1]][k - 1];
    35. }
    36. }
    37. }
    38. }
    39. int lca(int a,int b)
    40. {
    41. if(depth[a] < depth[b]) swap(a,b);
    42. for(int k = 16; k >= 0; k --)
    43. if(depth[fa[a][k]] >= depth[b])
    44. a = fa[a][k];
    45. if(a == b) return a;
    46. for(int k = 16; k >= 0; k --)
    47. if(fa[a][k] != fa[b][k])
    48. {
    49. a = fa[a][k];
    50. b = fa[b][k];
    51. }
    52. return fa[a][0];
    53. }
    54. int dfs(int u,int father,int id)
    55. {
    56. int res = d[u];
    57. for(int i = h[u]; ~i; i = ne[i])
    58. {
    59. int j = e[i];
    60. if(j == father) continue;
    61. int s = dfs(j,u,i);
    62. res += s;
    63. }
    64. if(res == m) ans = max(ans,id / 2 + 1);
    65. return res;
    66. }
    67. int main()
    68. {
    69. ans = -1;
    70. cin >> n >> m;
    71. memset(h,-1,sizeof h);
    72. for(int i = 0; i < n - 1; i ++)
    73. {
    74. int a,b;
    75. cin >> a >> b;
    76. add(a,b),add(b,a);
    77. }
    78. bfs();
    79. for(int i = 0; i < m; i ++)
    80. {
    81. int a,b;
    82. cin >> a >> b;
    83. int p = lca(a,b);
    84. d[a] ++,d[b] ++,d[p] -= 2;
    85. }
    86. dfs(1,-1,0);
    87. cout << ans << endl;
    88. return 0;
    89. }

  • 相关阅读:
    C++——string类
    阿里云弹性计算资源
    一键打包,随时运行,Python3项目虚拟环境一键整合包的制作(Venv)
    Python入门教学——if __name__==‘__main__‘:
    Bert基础(九)--Bert变体之ALBERT
    flask 插件 Flask-RESTful
    ElasticSearcch集群
    MySQL学生成绩管理系统based on C++ and Clion
    OpenCV4之特征提取与对象检测
    轻量级网络 ESPNetv2
  • 原文地址:https://blog.csdn.net/littlegengjie/article/details/134458841