H - Highways——最小生成树Kruskal算法+Prim算法

水深无声 2022-06-11 07:18 325阅读 0赞

Think:
1知识点:最小生成树Kruskal算法+Prim算法
2思考:
1>多组输入超时,单组输入AC——why???
2>排序时结构体内重载小于号快于再单独写cmp判断函数
3题意:需要使得n个结点构成连通图,已知有m个结点已经连接,询问最小花费构成连通图还需要连接那些结点
4思路:
1>Kruskal算法:先预处理所有结点距离,预处理结点距离时将其入队,之后按照权值排序,然后在通过并查集将已经连接的结点连成集合,记录有效边,进而按照已经排序的顺序更新试探,直到连接n个结点
2>Prim算法:先预处理所有结点距离,构造二维地图,然后通过已经连接的结点更新地图(可将地图中已经连接的结点预处理边权为0),进而Prim算法即可

vjudge题目链接

以下为Accepted代码——Prim算法-79ms

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int inf = 0x3f3f3f3f;
  6. struct Node{
  7. int x, y;
  8. }node[1014];
  9. struct Dist{
  10. int u;
  11. int w;
  12. }dis[1014];
  13. int vis[1014], e[1014][1014];
  14. void Prim(int n);
  15. int Dis(int u, int v);
  16. int main(){
  17. int n, m, i, j, u, v;
  18. scanf("%d", &n);
  19. for(i = 1; i <= n; i++)
  20. scanf("%d %d", &node[i].x, &node[i].y);
  21. for(i = 1; i <= n; i++){
  22. for(j = i+1; j <= n; j++){
  23. e[i][j] = e[j][i] = Dis(i, j);
  24. }
  25. }
  26. scanf("%d", &m);
  27. while(m--){
  28. scanf("%d %d", &u, &v);
  29. e[u][v] = e[v][u] = 0;
  30. }
  31. Prim(n);
  32. return 0;
  33. }
  34. int Dis(int u, int v){
  35. int dx = node[u].x - node[v].x;
  36. int dy = node[u].y - node[v].y;
  37. int dl = dx*dx + dy*dy;
  38. return dl;
  39. }
  40. void Prim(int n){
  41. int i, miv, v, num;
  42. memset(vis, 0, sizeof(vis));
  43. for(i = 1; i <= n; i++){
  44. dis[i].w = e[1][i];
  45. dis[i].u = 1;
  46. }
  47. vis[1] = 1, dis[1].w = 0, num = 1;
  48. while(num < n){
  49. miv = inf;
  50. for(i = 1; i <= n; i++){
  51. if(!vis[i] && dis[i].w < miv){
  52. miv = dis[i].w, v = i;
  53. }
  54. }
  55. vis[v] = 1, num++;
  56. if(e[v][dis[v].u])
  57. printf("%d %d\n", dis[v].u, v);
  58. for(i = 1; i <= n; i++){
  59. if(!vis[i] && e[v][i] < dis[i].w){
  60. dis[i].w = e[v][i];
  61. dis[i].u = v;
  62. }
  63. }
  64. }
  65. }

以下为Time Limit Exceeded代码——Kruskal算法-排序:单独写cmp判断函数

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <cmath>
  5. using namespace std;
  6. const double zero = 1e-4;
  7. struct Edge{
  8. int u;
  9. int v;
  10. int w;
  11. }edge[501400];
  12. struct Node{
  13. int x;
  14. int y;
  15. }node[1014];
  16. bool cmp(struct Edge a, struct Edge b){
  17. return a.w < b.w;
  18. }
  19. int tp, f[1014];
  20. void Init(int n);
  21. int get_f(int v);
  22. bool Merge(int u, int v);
  23. double Dis(int i, int j);
  24. int main(){
  25. int n, m, i, j, t, num, u, v;
  26. scanf("%d", &n);
  27. Init(n);
  28. for(i = 1; i <= n; i++){
  29. scanf("%d %d", &node[i].x, &node[i].y);
  30. }
  31. t = 0;
  32. for(i = 1; i <= n; i++){
  33. for(j = i+1; j <= n; j++){
  34. edge[t].u = i, edge[t].v = j;
  35. edge[t].w = Dis(i, j);
  36. t++;
  37. }
  38. }
  39. sort(edge, edge+t, cmp);
  40. num = 0;
  41. scanf("%d", &m);
  42. while(m--){
  43. scanf("%d %d", &u, &v);
  44. if(Merge(u, v))
  45. num++;
  46. }
  47. for(i = 0; i < t; i++){
  48. u = edge[i].u, v = edge[i].v;
  49. if(Merge(u, v)){
  50. printf("%d %d\n", u, v);
  51. num++;
  52. }
  53. if(num == n-1)
  54. break;
  55. }
  56. return 0;
  57. }
  58. void Init(int n){
  59. for(int i = 1; i <= n; i++)
  60. f[i] = i;
  61. }
  62. double Dis(int i, int j){
  63. int dx = node[i].x - node[j].x;
  64. int dy = node[i].y - node[j].y;
  65. int xy = dx*dx + dy*dy;
  66. return xy;
  67. }
  68. bool Merge(int u, int v){
  69. int t1 = get_f(u);
  70. int t2 = get_f(v);
  71. if(t1 != t2){
  72. f[t2] = t1;
  73. return true;
  74. }
  75. else
  76. return false;
  77. }
  78. int get_f(int v){
  79. if(f[v] == v)
  80. return f[v];
  81. f[v] = get_f(f[v]);
  82. return f[v];
  83. }

以下为Accepted代码——Kruskal算法-454ms-排序:结构体内重载小于号

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <cmath>
  5. using namespace std;
  6. const double zero = 1e-4;
  7. struct Edge{
  8. int u;
  9. int v;
  10. int w;
  11. bool operator < (const Edge &b)const{
  12. return w < b.w;
  13. }
  14. }edge[501400];
  15. struct Node{
  16. int x;
  17. int y;
  18. }node[1014];
  19. int tp, f[1014];
  20. void Init(int n);
  21. int get_f(int v);
  22. bool Merge(int u, int v);
  23. double Dis(int i, int j);
  24. int main(){
  25. int n, m, i, j, t, num, u, v;
  26. scanf("%d", &n);
  27. Init(n);
  28. for(i = 1; i <= n; i++){
  29. scanf("%d %d", &node[i].x, &node[i].y);
  30. }
  31. t = 0;
  32. for(i = 1; i <= n; i++){
  33. for(j = i+1; j <= n; j++){
  34. edge[t].u = i, edge[t].v = j;
  35. edge[t].w = Dis(i, j);
  36. t++;
  37. }
  38. }
  39. sort(edge, edge+t);
  40. num = 0;
  41. scanf("%d", &m);
  42. while(m--){
  43. scanf("%d %d", &u, &v);
  44. if(Merge(u, v))
  45. num++;
  46. }
  47. for(i = 0; i < t; i++){
  48. u = edge[i].u, v = edge[i].v;
  49. if(Merge(u, v)){
  50. printf("%d %d\n", u, v);
  51. num++;
  52. }
  53. if(num == n-1)
  54. break;
  55. }
  56. return 0;
  57. }
  58. void Init(int n){
  59. for(int i = 1; i <= n; i++)
  60. f[i] = i;
  61. }
  62. double Dis(int i, int j){
  63. int dx = node[i].x - node[j].x;
  64. int dy = node[i].y - node[j].y;
  65. int xy = dx*dx + dy*dy;
  66. return xy;
  67. }
  68. bool Merge(int u, int v){
  69. int t1 = get_f(u);
  70. int t2 = get_f(v);
  71. if(t1 != t2){
  72. f[t2] = t1;
  73. return true;
  74. }
  75. else
  76. return false;
  77. }
  78. int get_f(int v){
  79. if(f[v] == v)
  80. return f[v];
  81. f[v] = get_f(f[v]);
  82. return f[v];
  83. }

发表评论

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

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

相关阅读