BZOJ 2177: 曼哈頓最小生成樹 曼哈頓最小生成樹
阿新 • • 發佈:2019-01-04
2177: 曼哈頓最小生成樹
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 281 Solved: 117
[Submit][Status][Discuss]
Description
平面座標系xOy內,給定n個頂點V = (x , y)。對於頂點u、v,u與v之間的距離d定義為|xu – xv| + |yu – yv|
你的任務就是求出這n個頂點的最小生成樹。
Input
第一行一個正整數n,表示定點個數。
接下來n行每行兩個正整數x、y,描述一個頂點。
Output
只有一行,為最小生成樹的邊的距離和。
Sample Input
41 0
0 1
0 -1
-1 0
Sample Output
6HINT
對於100%的資料n <= 50000;
0 <= x, y <= 100000。#include<cmath> #include<ctime> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<iomanip> #include<vector> #include<string> #include<bitset> #include<queue> #include<map> #include<set> using namespace std; typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f; } void print(int x) {if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');} const int N=50100,inf=0X3f3f3f3f; int ecnt; struct EDGE { int u,v,val; friend bool operator <(const EDGE &x,const EDGE &y) {return x.val<y.val;} }e[N<<3]; struct node { int x,y,pos; friend bool operator <(const node &x,const node &y) {return x.x==y.x ? x.y<y.y : x.x<y.x;} }p[N]; inline int dis(int x,int y) {return abs(p[x].x-p[y].x)+abs(p[x].y-p[y].y);} int n; int V[N],tot; int bit[N],mn[N]; void initial() { register int i; sort(p+1,p+1+n); memset(mn,0,sizeof(mn)); memset(bit,0X3f,sizeof(bit)); for(i=1;i<=n;++i) V[i]=p[i].y-p[i].x; sort(V+1,V+1+n); for(i=2,tot=1;i<=n;++i) if(V[i]!=V[i-1]) V[++tot]=V[i]; } inline int get_hash(int x) { register int l(1),r(tot),mid; while(l<=r) { mid=(l+r)>>1; V[mid]<=x ? l=mid+1 : r=mid-1 ; } return l-1; } inline void modify(int x,int val,int pos) { for(;x;x-=(x&-x)) if(val<bit[x]) bit[x]=val,mn[x]=pos; } inline int query(int x) { int res(0),now(inf); for(;x<=tot;x+=(x&-x)) if(bit[x]<now) now=bit[x],res=mn[x]; return res; } int Fa[N]; inline int find(int x) {return Fa[x]==x ? x : Fa[x]=find(Fa[x]);} ll ans=0; void kruscal() { register int i; sort(e+1,e+1+ecnt); for(i=1;i<=n;++i) Fa[i]=i; for(i=1;i<=ecnt;++i) if(find(e[i].u)!=find(e[i].v)) Fa[Fa[e[i].u]]=Fa[e[i].v],ans+=e[i].val; } int main() { n=read(); //quadrant qd register int i,qd,pos,tmp; for(i=1;i<=n;++i) p[i].x=read(),p[i].y=read(),p[i].pos=i; for(qd=1;qd<5;++qd) { if(!(qd&1)) for(i=1;i<=n;++i) swap(p[i].x,p[i].y); else if(qd==3) for(i=1;i<=n;++i) p[i].x=-p[i].x; initial(); for(i=n;i;i--) { pos=get_hash(p[i].y-p[i].x); tmp=query(pos); if(tmp) e[++ecnt]=(EDGE){p[i].pos,p[tmp].pos,dis(i,tmp)}; modify(pos,p[i].x+p[i].y,i); } } kruscal(); cout<<ans<<endl; return 0; }