【洛谷P2504】聪明的猴子 最小瓶颈树

时间:2021-12-26 14:30:03

题目大意:给定一张 N 个顶点的完全图,边有边权,求该完全图的一棵最小瓶颈树。

最小瓶颈树:一棵最大边权值在同一张图的所有生成树中最小,即:最大边权值最小的生成树,其值为该树的最大边权的权值。

引理1:最小生成树一定是一棵最小瓶颈树。

证明:若最小生成树不是最小瓶颈树,则意味着存在一条边的权值大于最小瓶颈树的最大边权值,那么将 MST 的该边去掉,则将一棵树变成了不连通的两棵树,再将最小瓶颈树的一条连接这两个联通块的边加入 MST,可以得到一棵权值更小的生成树,与 MST 性质矛盾,证毕。

引理2:最小瓶颈树不一定是最小生成树。

证明:【洛谷P2504】聪明的猴子 最小瓶颈树

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxe=1e6+10;
const int maxv=1010; inline int read(){
int x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
} int n,m,tot,d[maxv>>1],f[maxv],sum,path,cnt;
struct node{int x,y;}p[maxv];
struct edge{int from,to,w;}e[maxe]; bool cmp(const edge& x,const edge& y){return x.w<y.w;} inline int get_dis(int a,int b){
return (p[a].x-p[b].x)*(p[a].x-p[b].x)+(p[a].y-p[b].y)*(p[a].y-p[b].y);
} void read_and_parse(){
m=read();
for(int i=1;i<=m;i++)d[i]=read();
sum=n=read();
for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read();
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
e[++tot]=edge{i,j,get_dis(i,j)};
} int find(int x){return x==f[x]?f[x]:f[x]=find(f[x]);} int kruskal(){
int src;
for(int i=1;i<=n;i++)f[i]=i;
sort(e+1,e+tot+1,cmp);
for(int i=1;i<=tot&&sum>1;i++){
int x=find(e[i].from),y=find(e[i].to);
if(x==y)continue;
f[x]=y,--sum,src=e[i].w;
}
return src;
} void solve(){
path=kruskal();
for(int i=1;i<=m;i++)if(d[i]*d[i]>=path)++cnt;
printf("%d\n",cnt);
} int main(){
read_and_parse();
solve();
return 0;
}