无线通讯网——kruskal算法

P1991 无线通讯网 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题看着很复杂,需要读几遍题才理解。题意可以转化为在图里去掉k-1条最小边后,第k条最小边即为答案。

因为在图中去掉n条边,就会得到n+1个连通块。那么就把所有哨所划分成了n+1个连通块,我们只需要在每个连通块里放一个卫星,这样不同连通块可以通过卫星联系,而每个连通块内部的哨所可以通过无线电来联系。所以当我们用kruskal算法将每个哨所之间的距离从小到大排好序后,因为有s个卫星、p个哨所,所以我们只需要将刚开始初始化的p个连通块用并查集转化为s个连通块就可以保证上述卫星与无线电的要求了。而为了转化为s个连通块,我们应该进行p-s次并查集的合并。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e5,M=600;
 4 int s,q,x[M],y[M],idx,p[M];
 5 struct node
 6 {
 7     int a,b;
 8     double w;
 9 }e[N];
10 
11 bool cmp(const node&s1,const node&s2)
12 {
13     return s1.w<s2.w;
14 }
15 
16 double juli(int i,int j)
17 {
18     double xx=(double)(x[i]-x[j]);
19     double yy=(double)(y[i]-y[j]);
20     return sqrt(xx*xx+yy*yy);
21 }
22 
23 int find(int x)
24 {
25     if(p[x]!=x)p[x]=find(p[x]);
26     return p[x];
27 }
28 
29 void kruskal()
30 {
31     sort(e+1,e+idx+1,cmp);
32     for(int i=1;i<=q;i++)p[i]=i;
33     
34     int k=0;double ans=0;
35     for(int i=1;i<=idx;i++)
36     {
37         int a=e[i].a,b=e[i].b;
38         double w=e[i].w;
39         if(find(a)!=find(b))
40         {
41             k++;
42             ans=w;
43             p[find(a)]=find(b);
44         }
45         if(k>=q-s)        //有s个连通块 
46         {
47             printf("%.2lf\n",ans);
48             return ;
49         }
50     }
51 }
52 
53 int main()
54 {
55     scanf("%d%d",&s,&q);
56     for(int i=1;i<=q;i++)scanf("%d%d",&x[i],&y[i]);
57     
58     for(int i=1;i<=q;i++)
59     {
60         for(int j=i+1;j<=q;j++)
61         {
62             double ww=juli(i,j);
63             e[++idx].a=i,e[idx].b=j,e[idx].w=ww;
64         }
65     }
66     
67     kruskal();
68     
69     return 0;
70 }
View Code

 

posted @ 2022-03-23 17:25  wellerency  阅读(25)  评论(0编辑  收藏  举报