【最小生成树】Battle Over Cities - Hard Version (35)

缺乏、安全感 2022-06-04 00:19 255阅读 0赞

Think:
1知识点:最小生成树
2题意:
(1):输入含有n(n<=500)个结点的连通图,询问最重要的点,最重要点的定义为删掉这个点及其所连的边,需要最多花费修复已经不再使用的边使得剩下的结点继续保持连通
(2):最重要的点可能有多个
3思路:
(1):记录所有边的信息,初始存在的边可置连接权值为0,遍历每一个点(假设删除当前遍历点及其所连的边,然后将其他n-1个点通过最小生成树算法连成连通图,记录花费)
4反思:
(1):最重要的点可能有多个
(2):删除一点之后可能之后的图不连通
(3):最重要的点输出顺序为按照字典序
(4):n == 1的情况需要特殊判断

以下为Accepted代码——Kruskal算法

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int inf = 0x3f3f3f3f;
  6. struct Edge{
  7. int u, v, w;
  8. bool operator < (const Edge &b) const{
  9. return w < b.w;
  10. }
  11. }edge[404014];
  12. struct Node{
  13. int id, sum_w;
  14. bool operator < (const Node &b) const{
  15. if(sum_w == b.sum_w) return id < b.id;
  16. return sum_w > b.sum_w;
  17. }
  18. }rec[504];
  19. int n, m;
  20. int f[504];
  21. void init_f();
  22. int get_f(int x);
  23. bool Merge(int x, int y);
  24. int Kruskal(int id);
  25. int main(){
  26. int sa;
  27. while(~scanf("%d %d", &n, &m)){
  28. if(n == 1){
  29. printf("0\n");
  30. }
  31. for(int i = 0; i < m; i++){
  32. scanf("%d %d %d %d", &edge[i].u, &edge[i].v, &edge[i].w, &sa);
  33. if(sa) edge[i].w = 0;
  34. }
  35. sort(edge, edge+m);
  36. for(int i = 1; i <= n; i++){
  37. rec[i].id = i;
  38. rec[i].sum_w = Kruskal(i);
  39. }
  40. sort(rec+1, rec+n+1);
  41. int mav = rec[1].sum_w;
  42. if(mav == 0){
  43. printf("0\n");
  44. }
  45. else {
  46. printf("%d", rec[1].id);
  47. for(int i = 2; i <= n; i++){
  48. if(rec[i].sum_w == mav){
  49. printf(" %d", rec[i].id);
  50. }
  51. else break;
  52. }
  53. printf("\n");
  54. }
  55. }
  56. return 0;
  57. }
  58. void init_f(){
  59. for(int i = 0; i <= n; i++)
  60. f[i] = i;
  61. return;
  62. }
  63. int get_f(int x){
  64. if(x == f[x]) return x;
  65. return f[x] = get_f(f[x]);
  66. }
  67. bool Merge(int x, int y){
  68. int t1 = get_f(x);
  69. int t2 = get_f(y);
  70. if(t1 == t2) return false;
  71. else {
  72. f[t2] = t1;
  73. return true;
  74. }
  75. }
  76. int Kruskal(int id){
  77. int num = 0, sum = 0;
  78. init_f();
  79. for(int i = 0; i < m; i++){
  80. if(edge[i].u == id || edge[i].v == id)
  81. continue;
  82. if(Merge(edge[i].u, edge[i].v)){
  83. num++;
  84. sum += edge[i].w;
  85. }
  86. if(num == n-2) break;
  87. }
  88. if(num == n-2) return sum;
  89. else return inf;
  90. }

发表评论

表情:
评论列表 (有 0 条评论,255人围观)

还没有评论,来说两句吧...

相关阅读