1 2 4 0 100 0 300 0 600 150 750
212.13
1).记Graph中有v个顶点。e个边
2).新建图Graphnew,Graphnew中拥有原图中同样的e个顶点,但没有边
3).将原图Graph中全部e个边按权值从小到大排序
4).循环:从权值最小的边开始遍历每条边 直至图Graph中全部的节点都在同一个连通分量中
if 这条边连接的两个节点于图Graphnew中不在同一个连通分量中
增加这条边到图Graphnew中
Prim算法:
1).输入:一个加权连通图。当中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},当中x为集合V中的任一节点(起始点),Enew = {},为空;
3).反复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,当中u为集合Vnew中的元素。而v不在Vnew集合当中。而且v∈V(如果存在有多条满足前述条件即具有同样权值的边,则可随意选取当中之中的一个);
b.将v增加集合Vnew中,将<u, v>边增加集合Enew中。
4).输出:使用集合Vnew和Enew来描写叙述所得到的最小生成树。
本题使用的是kruskal算法。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <cstdlib> 7 #include <algorithm> 8 using namespace std; 9 int T,s,n; 10 int x[505],y[505]; 11 struct Edge{ 12 int from,to; 13 double w; 14 }edge[300005]; 15 int tol; 16 int fa[505]; 17 void init(){ 18 tol = 0; 19 for (int i = 0;i < n;++i) fa[i] = i; 20 } 21 22 double dis(int i,int j){ 23 return sqrt((x[i]-x[j])*(x[i]-x[j]) + (y[i] - y[j]) * (y[i]-y[j])); 24 } 25 26 void addedge(int u,int v,double w){ 27 edge[tol++] = Edge{u,v,w}; 28 } 29 30 int getfa(int x){ 31 return ((x == fa[x]) ? x : fa[x] = getfa(fa[x])); 32 } 33 34 void Union(int x,int y){ 35 x = getfa(x); 36 y = getfa(y); 37 fa[x] = y; 38 } 39 40 double kruskal(){ 41 double ans = 0; 42 int pos = 0; 43 for (int i = 0;i < n-s;++i){ 44 while(getfa(edge[pos].from) == getfa(edge[pos].to)) pos++; 45 Union(edge[pos].from,edge[pos].to); 46 ans = edge[pos].w; 47 } 48 return ans; 49 } 50 51 bool cmp(Edge e1,Edge e2){ 52 return e1.w < e2.w; 53 } 54 55 int main(){ 56 scanf("%d",&T); 57 while(T--){ 58 scanf("%d%d",&s,&n); 59 for (int i = 0;i < n;++i){ 60 scanf("%d%d",x+i,y+i); 61 } 62 init(); 63 for (int i = 0;i < n-1;++i){ 64 for (int j = i+1;j < n;++j){ 65 addedge(i,j,dis(i,j)); 66 } 67 } 68 sort(edge,edge+tol,cmp); 69 printf("%.2f\n",kruskal()); 70 } 71 }
[2019北大机试G]:Arctic Network(最小生成树+并查集)
原文:https://www.cnblogs.com/mizersy/p/12256871.html