当前位置:   article > 正文

2023牛客暑期多校训练营1--K Subdivision(最短路树)

2023牛客暑期多校训练营1--K Subdivision(最短路树)

题目描述

You are given a graph with n vertices and m undirected edges of length 1. You can do the following operation on the graph for arbitrary times:

Choose an edge (u,v) and replace it by two edges, (u,w) and (w,v), where w is a newly inserted vertex. Both of the two edges are of length 1.

You need to find out the maximum number of vertices whose minimum distance to vertex 1 is no more than k.

输入描述:

The first line contains three integers n (1≤n≤10^5), m (0≤m≤2⋅10^5)and k (0≤k≤10^9).
Each of the next m lines contains two integers u and v (1≤u,v≤n), indicating an edge between u and v. It is guaranteed that there are no self-loops or multiple edges.

输出描述:
Output an integer indicating the maximum number of vertices whose minimum distance to vertex 1 is no more than k.

输入:

  1. 8 9 3
  2. 1 2
  3. 1 3
  4. 1 5
  5. 3 4
  6. 3 6
  7. 4 5
  8. 5 6
  9. 6 7
  10. 7 8

输出:

15

题意:给定n个点,m条边,k为给定数值,你有一种操作,相当于你选择一条边,加入任意个点,可以操作任意次,问最后从1出发能到达的点的总数最大。

解析:求一次bfs树,把非树边的边进行拓展 ,也同时把叶子节点进行拓展,此时就是最优的情况,至于证明,引用下官方题解专业证明.

注意:特判一下没有边的情况,遍历叶子节点时候直接从2开始,因为1为根节点,不能算叶子节点。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=2e5+5;
  4. typedef long long ll;
  5. typedef pair<int,ll> PII;
  6. vector<int> v[N];
  7. int in[N];//记录入度,入度为1即是叶子节点
  8. map<PII,int> mp;
  9. struct node
  10. {
  11. int a,b;
  12. bool flag;//是否为非树边
  13. }tr[N];
  14. ll dist[N];//记录从1出发到点u的距离
  15. void bfs()
  16. {
  17. queue<int> q;
  18. q.push(1);
  19. memset(dist,-1,sizeof dist);
  20. dist[1]=0;
  21. while(q.size())
  22. {
  23. int u=q.front();
  24. q.pop();
  25. for(int i=0;i<v[u].size();i++)
  26. {
  27. int j=v[u][i];
  28. if(dist[j]==-1)
  29. {
  30. dist[j]=dist[u]+1;
  31. q.push(j);
  32. tr[mp[{u,j}]].flag=true;//为树边
  33. tr[mp[{j,u}]].flag=true;//为树边
  34. }
  35. }
  36. }
  37. }
  38. void solve()
  39. {
  40. int n,m,k;
  41. scanf("%d%d%d",&n,&m,&k);
  42. for(int i=1;i<=m;i++)
  43. {
  44. int a,b;
  45. scanf("%d%d",&a,&b);
  46. tr[i]={a,b};
  47. mp[{a,b}]=i;
  48. v[a].push_back(b);
  49. v[b].push_back(a);
  50. in[a]++,in[b]++;
  51. }
  52. if(m==0)
  53. {
  54. printf("1\n");
  55. return;
  56. }
  57. bfs();
  58. ll ans=1;//自身
  59. for(int i=1;i<=m;i++)
  60. {
  61. int a=tr[i].a,b=tr[i].b;
  62. bool flag=tr[i].flag;
  63. if(!flag)//是非树边,进行拓展
  64. {
  65. //注意需要判断dist是否为-1,-1表示无法到达
  66. if(dist[a]<k&&dist[a]!=-1) ans+=k-dist[a];
  67. if(dist[b]<k&&dist[b]!=-1) ans+=k-dist[b];
  68. tr[mp[{a,b}]].flag=true;//此时表示已经使用过
  69. tr[mp[{b,a}]].flag=true;
  70. }
  71. }
  72. for(int i=2;i<=n;i++)
  73. {
  74. if(dist[i]!=-1&&in[i]==1&&dist[i]<k) ans+=k-dist[i];
  75. if(dist[i]!=-1&&dist[i]<=k) ans++;
  76. }
  77. printf("%lld\n",ans);
  78. }
  79. int main()
  80. {
  81. int t=1;
  82. //scanf("%d",&t);
  83. while(t--) solve();
  84. return 0;
  85. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/986534
推荐阅读
相关标签
  

闽ICP备14008679号