许久都没有做过图论题了,今天晚上刷了几道MST(最小生成树) 的题目,其中有一道题目还是很不错,在这里给大家推荐一下
链接在这里 : https://www.luogu.org/problem/P1991
看了题目之后,我们可以很清楚的知道题目需要我们先求连接所有哨所的最小花费,这时候这种连接点并求花费的算法自然就出来了,这里我们使用 Kruskal算法
一、我们先预处理任意两点的距离,存入结构体定义的边中
二、根据 Kruskal算法 的流程进行操作,当所有点被连上,退出
三、这时候答案就在way数组里第top-(s-1)中
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 const int N=502; 8 const int M=150000; 9 struct data{ 10 int x; 11 int y; 12 }pt[N]; 13 struct edge{ 14 int st; 15 int ed; 16 double val; 17 }eg[M]; 18 int tot=0; 19 int s,p; 20 int fa[N]; 21 double way[M]; 22 int top=0; 23 double ans; 24 int find(int x) 25 { 26 if (fa[x]==x) return x; 27 fa[x]=find(fa[x]); 28 return fa[x]; 29 } 30 inline void un(int x,int y) 31 { 32 int fx=find(x); 33 int fy=find(y); 34 if (fx!=fy) 35 fa[fx]=fy; 36 return; 37 } 38 double cd(int x1,int y1,int x2,int y2) 39 { 40 return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 41 } 42 bool cmp(edge a,edge b) 43 { 44 return a.val<b.val; 45 } 46 int main() 47 { 48 scanf("%d %d",&s,&p); 49 50 for (int i=1;i<=p;i++) 51 fa[i]=i; 52 53 for (int i=1;i<=p;i++) 54 scanf("%d %d",&pt[i].x,&pt[i].y); 55 56 for (int i=1;i<=p;i++) 57 for (int j=i+1;j<=p;j++) 58 { 59 int x1=pt[i].x,y1=pt[i].y; 60 int x2=pt[j].x,y2=pt[j].y; 61 double dis=cd(x1,y1,x2,y2); 62 eg[++tot].st=i,eg[tot].ed=j,eg[tot].val=dis; 63 } 64 sort(eg+1,eg+tot+1,cmp); 65 66 int cnt=0; 67 68 for (int i=1;i<=tot;i++) 69 { 70 int u=eg[i].st; 71 int v=eg[i].ed; 72 double w=eg[i].val; 73 if (find(u)!=find(v)) 74 { 75 un(u,v); 76 way[++top]=w; 77 ++cnt; 78 } 79 if (cnt==p-1) break; 80 } 81 ans=way[top-(s-1)]; 82 printf("%.2lf",ans); 83 return 0; 84 }
根据 Kruskal算法 我们的边都是从小到大排序,所以后加的边较大
一共 S 台卫星电话,所以可以连接最后的 S-1 点
所以最小的D就在 way[top-(s-1)] 中
原文:https://www.cnblogs.com/Snowindfly/p/11432040.html