loj6322 Star Way To Heaven Prim
阿新 • • 發佈:2020-10-13
Solution
首先想到二分答案,建圖,判斷上下邊界是否聯通,複雜度\(O(k^2logn)\),不能接受
由聯通,所以想到最小生成樹,在最小生成樹中,從下邊界到上邊界路徑上最長的邊 應該就是限制上下邊界聯通的邊,拿它除以 2 就是答案
此題邊數 \(m = k^2\),選擇prim \(O(k^2)\) ,因為kruskal 是 \(O(mlogm)\)
如果怕精度問題可以用 longlong 存下距離的平方
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define rint register int using namespace std; const int maxn=6e3+5; int n,m,k; int x[maxn],y[maxn]; double dis[maxn]; bool vis[maxn]; double cal(int i,int j){ if(i>j) swap(i,j); if(i==0&&j==k) return (double)m; if(i==0) return (double) y[j]; if(j==k) return (double) (double)m-y[i]; return (double)sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j])); } int main(){ // freopen("1.in","r",stdin); scanf("%d%d%d",&n,&m,&k); for(rint i=1;i<=k;++i) scanf("%d%d",&x[i],&y[i]); k++; for(rint i=1;i<=k;++i) dis[i]=1e18; for(rint i=1;i<=k+1;++i){ double min_dis=1e18; rint x=-1; for(rint j=0;j<=k;++j){ if(!vis[j] && min_dis>dis[j]){ x=j; min_dis=dis[j]; } } if(x==k){ printf("%.8lf\n",dis[k]/2);return 0;} vis[x]=1; for(rint j=1;j<=k;++j) if(!vis[j]) dis[j]=min(dis[j],max(dis[x],cal(x,j))); // dis[j] 是MST中j到下邊界路徑上最大邊長(因為MST上不斷拓展的新點dis單調不減,所以這樣也可以求出MST) } return 0; }