链接:https://www.luogu.com.cn/problem/P1991
虽然实现起来是套一个最小生成树模板,但想简单写一下看法。为什么有s个卫星电话就能减去最大的s-1条边呢?首先我们给生成树最大边的两个端点用上卫星电话,同时去掉最大边。接下来,对于目前生成树的最大边,假设有一个端点有卫星电话,那么我们给另一个装上卫星电话,同时去掉最大边;如果两个端点都无卫星电话,此时如果去掉这条边,生成树会变成两个连通分支,我们只需从一个连通分支装有卫星电话的点连一条边到另一个连通分支上,就能重新连通。这样每次我们都能删去最大边,最多删去s-1条边。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 #include <queue> 6 #include <vector> 7 #include <map> 8 #include <cstdlib> 9 #include <cstring> 10 #include <cmath> 11 #include <set> 12 #include <cctype> 13 using namespace std; 14 typedef long long ll; 15 typedef pair <int,int> pii; 16 int s,p,cnt,res; 17 int f[510],node[510][2]; 18 struct edge 19 { 20 int u,v; 21 double w; 22 }e[300000]; 23 bool cmp(edge a,edge b) 24 { 25 return a.w<b.w; 26 } 27 int find(int k) 28 { 29 if(f[k]==k)return k; 30 return f[k]=find(f[k]); 31 } 32 int main(void) 33 { 34 scanf("%d %d",&s,&p); 35 for(int i=1;i<=p;++i) 36 { 37 f[i]=i; 38 scanf("%d %d",&node[i][0],&node[i][1]); 39 } 40 for(int i=1;i<=p;++i) 41 { 42 for(int j=i+1;j<=p;++j) 43 { 44 ++cnt; 45 e[cnt].u=i;e[cnt].v=j; 46 e[cnt].w=sqrt((node[i][0]-node[j][0])*(node[i][0]-node[j][0])+(node[i][1]-node[j][1])*(node[i][1]-node[j][1])); 47 } 48 } 49 sort(e+1,e+1+cnt,cmp); 50 for(int i=1;i<=cnt;++i) 51 { 52 int fu=find(e[i].u),fv=find(e[i].v); 53 if(fu==fv)continue; 54 f[fu]=fv; 55 if(++res==p-s) 56 { 57 printf("%.2f ",e[i].w);
58 return 0; 59 } 60 }
61 }