最小生成树(kruskal模版 Prim模板)

http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2144&cid=1186

最小生成树,最重要的是了解思想

稠密图用Prim,稀疏图用Kruskal

K(每次找最小的边连接,一条边连接两个点,所以单路就可以了)

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 int bin[110];
 5 struct node
 6 {
 7     int u,v,w;
 8 }q[10001];
 9
10 int cmp(const void *a,const void *b)//按距离从小到大排序
11 {
12     return (*(node *)a).w-(*(node *)b).w;
13 }
14 int find(int a)
15 {
16    if(a==bin[a])
17    return a;
18    else
19    bin[a]=find(bin[a]);
20 };
21 int main()
22 {
23     int n,m,i,j,sum,num;
24     int x,y;
25     while(~scanf("%d%d",&n,&m))
26     {
27         sum=0; num=0;
28         for(i=1; i<=n; i++)
29         bin[i]=i;
30         for(i=0; i<=m-1; i++)
31             scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w);
32         qsort(q,m,sizeof(q[0]),cmp);
33      这是重点思想 for(i=0; i<=m-1; i++)
34         {
35             x=find(q[i].u); y=find(q[i].v);
36             if(x!=y)  //检查是否连通
37             {
38                 sum+=q[i].w;//没连通的话加上距离
39                 num++;   //城市+1
40                 bin[x]=y;
41             }
42             if(num==n-1)
43             break;
44         }
45         printf("%d\n",sum);
46     }
47 }

Prim()

  1. #include <stdio.h>
  2. #include <string.h>
  3. #define N 1000001
  4. int map[110][110];
  5. int vis[110];
  6. int dis[110];
  7. int n,m;
  8. void prim()
  9. {
  10. int ans=0;
  11. int i,j;
  12. memset(vis,0,sizeof(vis));
  13. memset(dis,0,sizeof(dis));
  14. for(i = 1; i <= n; i++)
  15. dis[i] = map[1][i];
  16. vis[1] = 1;
  17. for(i = 1; i <= n-1; i++)
  18. {
  19. int pos;
  20. int min;
  21. min = N;
  22. for(j = 1; j <= n; j++)
  23. {
  24. if(vis[j]==0&&min>dis[j])
  25. {
  26. pos=j;
  27. min=dis[j];
  28. }
  29. }
  30. vis[pos]  = 1;
  31. ans += min;
  32. for(j = 1; j <= n; j++)
  33. {
  34. if(vis[j]==0&& dis[j]>map[pos][j])
  35. dis[j]=map[pos][j];
  36. }
  37. }
  38. printf("%d\n",ans);
  39. return ;
  40. }
  41. int main()
  42. {
  43. int a,b,c;
  44. int i,j;
  45. while(scanf("%d %d",&n,&m)!=EOF)
  46. {
  47. for(i=1; i<=n; i++)
  48. {
  49. for(j=1; j<=n; j++)
  50. {
  51. map[i][j]=N;
  52. map[j][i]=N;
  53. }
  54. map[i][i]=0;
  55. }
  56. for(i=1;i<=m;i++)
  57. {
  58. scanf("%d%d%d",&a,&b,&c);
  59. if(c<map[a][b])
  60. {
  61. map[a][b]=c;
  62. map[b][a]=c;
  63. }
  64. }
  65. prim();
  66. }
  67. return 0;
  68. }

最小生成树(kruskal模版 Prim模板),布布扣,bubuko.com

时间: 2024-12-20 11:46:32

最小生成树(kruskal模版 Prim模板)的相关文章

【模版】最小生成树Kruskal模版

最小生成树简单来说就是在一个有$n$条边的有权无向连通图中选出$n-1$条边,使图连通并且这$n-1$条边的边权和最小. Kruskal算法是用一种贪心的思想,先将所有的边按边权排序,按边权从小到大顺序枚举边,如果起点和终点不在一个集合,就选这条边,并将起点和终点合并成一个集合:反之则不选此边.集合可以用并查集维护. (以上内容纯属瞎编,若要系统学习请百度) 下面是模版 //最小生成树(Kruskal)模版 //By LC 2017.2.19整理 #include <cstdio> #incl

HDU 1233 还是畅通工程【最小生成树入门题,Kruskal算法+Prim算法】

还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 39929    Accepted Submission(s): 18144 Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路

hdu 1162 Eddy&#39;s picture 最小生成树入门题 Prim+Kruskal两种算法AC

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7428    Accepted Submission(s): 3770 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to

稀疏图(邻接链表),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)

#include<iostream> #include<vector> #include<queue> #include<stack> #include<algorithm> #include<stdio.h> #include<stdlib.h> using namespace std; /* //函数集合声明下,方便查看 void Dijkstra(const denseGraph& dg, int s); v

模板——最小生成树kruskal算法+并查集数据结构

并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每个点只保存祖先,不保存父亲) 最小生成树kruskal:贪心算法+并查集数据结构,根据边的多少决定时间复杂度,适合于稀疏图 核心思想贪心,找到最小权值的边,判断此边连接的两个顶点是否已连接,若没连接则连接,总权值+=此边权值,已连接就舍弃继续向下寻找: 并查集数据结构程序: #include<ios

最小生成树 Kruskal算法

Kruskal算法 1.概览 Kruskal算法是一种用来寻找最小生成树的算法,由Joseph Kruskal在1956年发表.用来解决同样问题的还有Prim算法和Boruvka算法等.三种算法都是贪婪算法的应用.和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效. 2.算法简单描述 1).记Graph中有v个顶点,e个边 2).新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边 3).将原图Graph中所有e个边按权值从小到大排序 4)

hihocoder(1098) 最小生成树Kruskal

Kruskal比Prim简单的多,对已知边排序,然后从排序的边中跳出N-1条最短的来就可以了,当然,如果在挑的过程中出现环,就丢掉继续找,就只这么直接. 如何判定有没有环?很简单,用并查集就可以. 比如a-b,b-c,c-a构成了环,那么a-b合并,b-c合并后,如果紧接着最小边是c-a,那么并查集的find(c,a)操作就会告诉你,c,a是同一个环内,跳过,继续. 总结一下: (1)对已知边排序(如果用数组存顶点,那么直接用qsort()就行了,如果用vector,那么sort()就行了) (

最小生成树(kruskal+并查集)

最小生成树 最小生成树即用最少的边权将所有给定的点连在同一联通分量中,常用kruskal和prim算法 kruskal算法(适合稀疏图) 最小生成树的kruskal算法,稍带并查集的应用 int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); //不要漏了fa[x]=... } int kruskal() { int ans=0; for(int i=0;i<N;i++) fa[i]=i;//初始化并查集 sort(edge,edge+e);

SOJ4339 Driving Range 最小生成树 kruskal算法

典型的最小生成树 然后求最大的一条边 附上链接 http://cstest.scu.edu.cn/soj/problem.action?id=4339 需要注意的是有可能有 "IMPOSSIBLE" 的情况 这里用一个flag标记 记录所并的节点 只有flag = n时才能成功 负责就 "IMPOSSIBLE" 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring&g