1. 程式人生 > >【洛谷習題】公路修建

【洛谷習題】公路修建

距離 完全 鏈接 main 稠密圖 呵呵 class 不用 scan

本想著做完這道題,就暫時告別MST,但越到了這個時候,驚喜也就越多,呵呵。

題目鏈接:https://www.luogu.org/problemnew/show/P1265


哎,上去就mengbi第二個規則,自己試了好半天,始終舉不出例子來,只好去看題解,,,真想吐血!原來第二種情況根本不存在,這道題其實也是要求最小生成樹!

好,Kruskal上!砰!

n<=5000?那麽邊數最多可有25000000!顯然內存方面就會炸。

再仔細一看題解,哦,是用Prim。記得曾經dalao和我說過,Prim並不是一無是處,他就用到過一次,當時沒仔細聽,沒想到最終還是翻了船。

去啃Prim,發現確實Kruskal不能完全代替他。具體詳見另一篇博客《Prim算法》。

邊是不可以全部保存的,而Prim算法的過程剛好可以不用保存每條邊,只需動態查詢邊的長度即可。Prim適用於稠密圖,所以這道題非Prim莫屬了。

高高興興寫上Prim提交。。。什麽!只有10分?找了好半天都不知道哪錯了,摁著正解使勁讀,最後才意識到求兩點間距離時原來會溢出。

比如:sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)),萬一坐標的範圍很大,中間過程(像(x1-x2)*(x1-x2))就會溢出!

唔,可算是完了。

技術分享圖片
 1 #include<cstdio>
 2 #include<cmath>
 3 const int maxn=5005
; 4 const double inf=1e9; 5 int n,x[maxn],y[maxn],vis[maxn]; 6 double minw[maxn],ans=0; 7 double dis(int i,int j) { 8 return sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j])); 9 } //一定要註意這裏別溢出!!! 10 int main() { 11 scanf("%d",&n); 12 for(int i=1;i<=n;++i) scanf("
%d%d",&x[i],&y[i]); 13 int index; 14 double mmin; 15 for(int i=2;i<=n;++i) minw[i]=inf; 16 for(int i=1;i<=n;++i) { 17 mmin=inf; 18 for(int j=1;j<=n;++j) if(!vis[j]&&minw[j]<mmin) index=j,mmin=minw[j]; 19 vis[index]=1; 20 ans+=mmin; 21 for(int j=1;j<=n;++j) { 22 double d=dis(index,j); 23 if(!vis[j]&&d<minw[j]) minw[j]=d; 24 } 25 } 26 printf("%.2f",ans); 27 return 0; 28 }
AC代碼

【洛谷習題】公路修建