JZOJ 5353 村通網
Description
為了加快社會主義現代化,建設新農村,農夫約(Farmer Jo)決定給農莊裡每座建築都連上網際網路,方便未來隨時隨地網購農藥。
他的農莊很大,有N 座建築,但地理位置偏僻,網路訊號很差。
一座建築有網,當且僅當滿足以下至少一個條件:
1、給中國移動交寬頻費,直接連網,花費為A。
2、向另外一座有網的建築,安裝共享網線,花費為B×兩者曼哈頓距離。
現在,農夫約已經統計出了所有建築的座標。他想知道最少要多少費用才能達到目的。
Input
第一行:三個正整數,代表N、A、B。
接下來N 行:每行兩個整數Xi、Yi,第i 行代表第i 座建築的座標。
Output
第一行:一個整數,代表答案。
Sample Input
5 10 2
0 0
0 1
1 0
1 1
100 100
Sample Output
26
Data Constraint
30%的資料:N <= 3,A <= 50,B <= 5
60%的資料:N <= 100,A <= 1000,B <= 20
100%的資料:N <= 10^3,A <= 10^4,B <= 50,|Xi|,|Yi| < 2^15
題目大意:給出n個點,按照聯通方式求最小連線價值。
演算法:Kruscal
程式碼:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; long long num,cnt,ans,n,a,b,fa[10001]; bool vis[100001]; struct node { int x,y; }city[1000001]; struct Edge { int from,to,w; }edge[1000001]; inline int read() { int x=0; bool w=false; char ch=0; while(!isdigit(ch)) { w|=ch=='-'; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return w?-x:x; } inline bool cmp(Edge a,Edge b) { return a.w<b.w; } inline int find(int x) { int t=x,pre; while(t!=fa[t]) t=fa[t]; while(x!=t) { pre=fa[x]; fa[x]=t; x=pre; } return t; } inline void addedge(int u,int v,int w) { edge[++num].from=u; edge[num].to=v; edge[num].w=w; } inline void kruscal() { for(register int i=1;i<=n;i++) fa[i]=i; for(register int i=1;i<=num;i++) { if(edge[i].w>a) continue; int fx=find(edge[i].from),fy=find(edge[i].to); if(fx==fy) continue; fa[fx]=fy; cnt++; ans+=edge[i].w; if(cnt==num-1) break; } } int main() { n=read(); a=read();b=read(); for(register int i=1;i<=n;i++) { city[i].x=read(); city[i].y=read(); } for(register int i=1;i<=n;i++) for(register int j=i+1;j<=n;j++) addedge(i,j,b*abs(abs(city[i].x-city[j].x)+abs(city[i].y-city[j].y))); sort(edge+1,edge+num+1,cmp); kruscal(); for(register int i=1;i<=n;i++) vis[find(i)]++; for(register int i=1;i<=n;i++) if(vis[i]) ans+=a; printf("%lld\n",ans); fclose(stdin); fclose(stdout); return 0; }