A - Jungle Roads——最小生成树

曾经终败给现在 2022-06-12 14:39 258阅读 0赞

Think:
1知识点:最小生成树
2题意分析:n个村庄选择可以将n个村庄连通的n-1条路进行维护,询问最小维护费用,即n个结点选择n-1条边建立最小生成树
3反思:Prim()算法注意结点记录变量初始化应为1,以及地图信息记录数组初始化应为inf(0x3f3f3f3f)——当前题目
4思考:Kruskal算法适用于稀疏图时间复杂度m+nlg(n),未堆优化的Prim算法适用于稠密图时间复杂度n^2

vjudge题目链接

以下为Accepted代码——Kruskal算法

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. struct Edge{
  6. int u, v, w;
  7. bool operator < (const Edge &b) const{
  8. return w < b.w;
  9. }
  10. }link[2014];
  11. int tp, f[40];
  12. void add_edge(int u, int v, int w);
  13. void Init(int n);
  14. int get_f(int x);
  15. bool Merge(int x, int y);
  16. void Kruskal(int n);
  17. int main(){
  18. int n, i, k, u, v, w;
  19. char st[14];
  20. while(~scanf("%d", &n) && n){
  21. tp = 0;
  22. for(i = 1; i < n; i++){
  23. scanf("%s %d", st, &k);
  24. u = st[0] - 'A' + 1;
  25. while(k--){
  26. scanf("%s %d", st, &w);
  27. v = st[0] - 'A' + 1;
  28. add_edge(u, v, w);
  29. }
  30. }
  31. Kruskal(n);
  32. }
  33. return 0;
  34. }
  35. void add_edge(int u, int v, int w){
  36. link[tp].u = u;
  37. link[tp].v = v;
  38. link[tp].w = w;
  39. tp++;
  40. }
  41. void Kruskal(int n){
  42. Init(n);
  43. sort(link, link+tp);
  44. int cnt = 0, sum = 0;
  45. for(int i = 0; i < tp; i++){
  46. int x = link[i].u;
  47. int y = link[i].v;
  48. if(Merge(x, y)){
  49. cnt++;
  50. sum += link[i].w;
  51. if(cnt == n-1)
  52. break;
  53. }
  54. }
  55. printf("%d\n", sum);
  56. }
  57. void Init(int n){
  58. for(int i = 0; i <= n; i++)
  59. f[i] = i;
  60. }
  61. int get_f(int x){
  62. if(f[x] == x)
  63. return x;
  64. return f[x] = get_f(f[x]);
  65. }
  66. bool Merge(int x, int y){
  67. int t1 = get_f(x);
  68. int t2 = get_f(y);
  69. if(t1 == t2)
  70. return false;
  71. else {
  72. f[t2] = t1;
  73. return true;
  74. }
  75. }

以下为Accepted代码——Prim算法

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int inf = 0x3f3f3f3f;
  6. int e[42][42], dis[42], vis[42];
  7. void Prim(int n);
  8. int main(){
  9. int n, i, k, u, v, w;
  10. char st1[14], st2[14];
  11. while(scanf("%d", &n) && n){
  12. getchar();
  13. memset(e, inf, sizeof(e));
  14. for(i = 1; i < n; i++){
  15. scanf("%s %d", st1, &k);
  16. u = st1[0]-'A'+1;
  17. while(k--){
  18. scanf("%s %d", st2, &w);
  19. v = st2[0]-'A'+1;
  20. e[u][v] = e[v][u] = w;
  21. }
  22. }
  23. Prim(n);
  24. }
  25. return 0;
  26. }
  27. void Prim(int n){
  28. int i, v, miv, num, sum;
  29. memset(vis, 0, sizeof(vis));
  30. for(i = 1; i <= n; i++)
  31. dis[i] = e[1][i];
  32. vis[1] = 1, dis[1] = 0, num = 1, sum = 0;
  33. while(num < n){
  34. miv = inf;
  35. for(i = 1; i <= n; i++){
  36. if(!vis[i] && dis[i] < miv){
  37. miv = dis[i], v = i;
  38. }
  39. }
  40. vis[v] = 1, num++, sum += dis[v];
  41. for(i = 1; i <= n; i++){
  42. if(!vis[i] && e[v][i] < dis[i])
  43. dis[i] = e[v][i];
  44. }
  45. }
  46. printf("%d\n", sum);
  47. }

发表评论

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

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

相关阅读