D136 最小生成树 Kruskal 算法 P8191 [USACO22FEB] Moo Network G
D136 最小生成树 Kruskal 算法 P8191 [USACO22FEB] Moo Network G_哔哩哔哩_bilibili
P8191 [USACO22FEB] Moo Network G - 洛谷 P2872 [USACO07DEC] Building Roads S - 洛谷
给定 n 个点的坐标,求连通 n 个点的最低成本。
思路
两题的思路都是求最小生成树,但是数据范围不同
P2872:$n\le 1000,1\le x,y\le 10^6$,$n$ 个点直接双重循环建图
P8191:$n\le 100000,0\le x\le 10^6,0\le y\le 10$,$n$ 个点不能双重循环建图
坐标点都取整数且分布在一个狭长的区带,每个点只需要连 “附近” 的点,先对 $n$ 个点按 $x$ 坐标排序
这个 “附近” 究竟是多少呢?

考虑最坏情况,$\frac{1}{4}$ 圆内仅圆心 $O(0,10)$ 一个点,圆弧外的格点数用程序求出为 $31$ 个,再取圆弧上的一点 $A(10,10)$
弧外的 $31$ 个点的排序均介于 $O$ 点与 $A$ 点之间,$O$ 点需要先连上 $31$ 个点,再连上 $A$ 点,$OA$ 就是一条最小生成树的边
所以,每个点向后连至少 $32$ 个点,洛谷上的题解都没有论证这个下界,连接点数少于 $32$,就会被下面构造的数据 $Hack$ 掉
相关板子:
D08【模板】最小生成树 Kruskal 算法 - 董晓 - 博客园
圆内格点数可参考: 高斯圆问题-数学百科
// Kruskal算法 O(mlogm) #include<bits/stdc++.h> #define int long long #define pii pair<int,int> using namespace std; const int N=1e5+5,M=3.2e6+5; int n,m,ans,tot,fa[N]; struct A{int x,y;} a[N]; //坐标 struct E{int x,y,d;} e[M]; //边集 int find(int u){ //并查集的找根 return fa[u]==u?u:fa[u]=find(fa[u]); } void kruskal(){ for(int i=1;i<=n;i++) fa[i]=i; sort(e+1,e+1+m,[&](E a,E b){return a.d<b.d;}); for(int i=1;i<=m;i++){ int x=find(e[i].x),y=find(e[i].y); if(x!=y){ fa[x]=y; ans+=e[i].d; if(++tot==n-1) break; } } printf("%lld\n",ans); } signed main(){ scanf("%lld",&n); for(int i=1,x,y;i<=n;i++){ scanf("%lld%lld",&x,&y); a[i]={x,y}; } sort(a+1,a+n+1,[&](A a,A b){ if(a.x!=b.x) return a.x<b.x; return a.y<b.y; }); for(int i=1;i<=n-1;i++)for(int j=i+1; j<=min(i+32,n); j++){ e[++m]={i,j,(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)}; } kruskal(); }
// 构造 Hack 数据 #include<bits/stdc++.h> using namespace std; int main(){ int s=0; for(int x=0;x<=10;x++) for(int y=0;y<=10;y++) if(x*x+(10-y)*(10-y)>10*10) s++; printf("%d\n",s+2); //弧外31个点+两个点 printf("%d %d\n",0,10); //圆心 for(int x=0;x<=10;x++) for(int y=0;y<=10;y++) if(x*x+(10-y)*(10-y)>10*10) printf("%d %d\n",x,y); printf("%d %d\n",10,10); //补个弧上点 }
Hack 数据,正确答案 131
33 0 10 1 0 2 0 3 0 4 0 5 0 5 1 6 0 6 1 7 0 7 1 7 2 8 0 8 1 8 2 8 3 9 0 9 1 9 2 9 3 9 4 9 5 10 0 10 1 10 2 10 3 10 4 10 5 10 6 10 7 10 8 10 9 10 10
浙公网安备 33010602011771号