POJ-3241 Object Clustering 曼哈顿最小生成树
2013-08-18 16:47
381 查看
题目链接:http://poj.org/problem?id=3241
题意:平面上有n个点集,现在把他们分成k个集合,使得每个集合中的每个点都至少有一个本集合的点之间的曼哈顿距离不大于X,求最小的X。
题目要求划分集合之后,每个集合的曼哈顿最小生成树的最长边不超过X,那么容易想到就是整个点集的曼哈顿最小生成树的第n-k条边。。
那么主要就是求曼哈顿最小生树的问题了,有O(logn)的算法可以轻松解决建图的问题,主要是利用到了环切的性质,考虑到很多边其实都是没有用的:对于某个点,以他为中心的区域分为8个象限,对于每一个象限,只会取距离最近的一个点连边。。
如果这样建立边的话需要建立8次,但是考虑到对称性,实际上我们只要建立4次就够了,R1,R2,R3,R4。再来看看R1和R2区域点集需要满足的条件,
R1:1. x≥xk 2.y-x>yk-xk R2:1.x≥xk 2.y-x<yk-xk
这里只是一个>和<小于的区别,因此我们完全只需要两次就够了。。。
还可以用坐标变化来求,R1:y-x>yk-xk R2:y-x<yk-xk R3:y+x>yk+xk R4:y+x<yk+xk
R1->R2:关于y=x对称,swap(x,y)
R2->R3:考虑到代码的方便性,我们考虑R2->R7,x=-x。
R7->R4:因为上面求的是R2->R7,因此这里还是关于y=x对称。。
然后用个BIT维护就可以了,不要问我BIT是什么Binary Indexed Trees。。
题意:平面上有n个点集,现在把他们分成k个集合,使得每个集合中的每个点都至少有一个本集合的点之间的曼哈顿距离不大于X,求最小的X。
题目要求划分集合之后,每个集合的曼哈顿最小生成树的最长边不超过X,那么容易想到就是整个点集的曼哈顿最小生成树的第n-k条边。。
那么主要就是求曼哈顿最小生树的问题了,有O(logn)的算法可以轻松解决建图的问题,主要是利用到了环切的性质,考虑到很多边其实都是没有用的:对于某个点,以他为中心的区域分为8个象限,对于每一个象限,只会取距离最近的一个点连边。。
如果这样建立边的话需要建立8次,但是考虑到对称性,实际上我们只要建立4次就够了,R1,R2,R3,R4。再来看看R1和R2区域点集需要满足的条件,
R1:1. x≥xk 2.y-x>yk-xk R2:1.x≥xk 2.y-x<yk-xk
这里只是一个>和<小于的区别,因此我们完全只需要两次就够了。。。
还可以用坐标变化来求,R1:y-x>yk-xk R2:y-x<yk-xk R3:y+x>yk+xk R4:y+x<yk+xk
R1->R2:关于y=x对称,swap(x,y)
R2->R3:考虑到代码的方便性,我们考虑R2->R7,x=-x。
R7->R4:因为上面求的是R2->R7,因此这里还是关于y=x对称。。
然后用个BIT维护就可以了,不要问我BIT是什么Binary Indexed Trees。。
//STATUS:C++_AC_79MS_884KB #include <functional> #include <algorithm> #include <iostream> //#include <ext/rope> #include <fstream> #include <sstream> #include <iomanip> #include <numeric> #include <cstring> #include <cassert> #include <cstdio> #include <string> #include <vector> #include <bitset> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <list> #include <set> #include <map> using namespace std; //#pragma comment(linker,"/STACK:102400000,102400000") //using namespace __gnu_cxx; //define #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define PI acos(-1.0) //typedef typedef __int64 LL; typedef unsigned __int64 ULL; //const const int N=10010; const int INF=0x3f3f3f3f; const int MOD=100000,STA=8000010; const LL LNF=1LL<<60; const double EPS=1e-8; const double OO=1e15; const int dx[4]={-1,0,1,0}; const int dy[4]={0,1,0,-1}; const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; //Daily Use ... inline int sign(double x){return (x>EPS)-(x<-EPS);} template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} template<class T> inline T lcm(T a,T b,T d){return a/d*b;} template<class T> inline T Min(T a,T b){return a<b?a:b;} template<class T> inline T Max(T a,T b){return a>b?a:b;} template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} // struct Point{ int x,y,id; bool operator<(const Point p)const{ return x!=p.x?x<p.x:y<p.y; } }p ; struct BIT{ int min_val,pos; void init(){ min_val=INF; pos=-1; } }bit ; struct Edge{ int u,v,d; bool operator<(const Edge e)const{ return d<e.d; } }e[N<<2]; int T ,hs ; int n,mt,pre ; void adde(int u,int v,int d) { e[mt].u=u,e[mt].v=v; e[mt++].d=d; } int find(int x) { return pre[x]=(x==pre[x]?x:find(pre[x])); } int dist(int i,int j) { return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y); } inline int lowbit(int x) { return x&(-x); } void update(int x,int val,int pos) { for(int i=x;i>=1;i-=lowbit(i)) if(val<bit[i].min_val) bit[i].min_val=val,bit[i].pos=pos; } int query(int x,int m) { int min_val=INF,pos=-1; for(int i=x;i<=m;i+=lowbit(i)) if(bit[i].min_val<min_val) min_val=bit[i].min_val,pos=bit[i].pos; return pos; } int Manhattan_minimum_spanning_tree(int n,Point *p,int K) { int i,w,dir,fa,fb,pos,m; //Build graph mt=0; for(dir=0;dir<4;dir++){ //Coordinate transform - reflect by y=x and reflect by x=0 if(dir==1||dir==3){ for(i=0;i<n;i++) swap(p[i].x,p[i].y); } else if(dir==2){ for(i=0;i<n;i++){ p[i].x=-p[i].x; } } //Sort points according to x-coordinate sort(p,p+n); //Discretize for(i=0;i<n;i++){ T[i]=hs[i]=p[i].y-p[i].x; } sort(hs,hs+n); m=unique(hs,hs+n)-hs; //Initialize BIT for(i=1;i<=m;i++) bit[i].init(); //Find points and add edges for(i=n-1;i>=0;i--){ pos=lower_bound(hs,hs+m,T[i])-hs+1; //BIT中从1开始' w=query(pos,m); if(w!=-1) adde(p[i].id,p[w].id,dist(i,w)); update(pos,p[i].x+p[i].y,i); } } //Kruskal - 找到第K小的边 sort(e,e+mt); for(i=0;i<n;i++)pre[i]=i; for(i=0;i<mt;i++){ fa=find(e[i].u),fb=find(e[i].v); if(fa!=fb){ K--;pre[fa]=fb; if(K==0)return e[i].d; } } } int main(){ // freopen("in.txt","r",stdin); int i,j,k; while(~scanf("%d%d",&n,&k)) { for(i=0;i<n;i++){ scanf("%d%d",&p[i].x,&p[i].y); p[i].id=i; } printf("%d\n",Manhattan_minimum_spanning_tree(n,p,n-k)); } return 0; }
相关文章推荐
- poj 3241 Object Clustering(曼哈顿最小生成树)
- poj 3241 Object Clustering 莫队算法,曼哈顿最小生成树
- POJ 3241 Object Clustering 曼哈顿距离求最小生成树的第K小边
- 平面点曼哈顿最小生成树——POJ 3241 Object Clustering
- POJ - 3241 Object Clustering(莫队算法/曼哈顿最小生成树)
- poj 3241 Object Clustering (曼哈顿距离最小生成树)
- poj 3241 Object Clustering 曼哈顿最小生成树
- POJ 3241 Object Clustering 平面曼哈顿最小生成树
- 【POJ 3241】Object Clustering 曼哈顿距离最小生成树
- POJ 3241 Object Clustering 曼哈顿距离最小生成树
- Object Clustering - POJ 3241 曼哈顿最小生成树
- POJ 3241 Object Clustering (曼哈顿距离最小生成树)
- poj 3241 Object Clustering 曼哈顿最小生成树
- POJ 3241 Object Clustering 曼哈顿最小生成树
- [曼哈顿距离最小生成树 模板题] POJ 3241 Object Clustering
- POJ 3241 Object Clustering 二维平面曼哈顿距离最小生成树
- POJ - 3241 Object Clustering 哈夫曼距离最小生成树
- 【POJ 3241】曼哈顿最小生成树(模板整理)
- POJ 3241 曼哈顿距离最小生成树 Object Clustering
- POJ 3241 曼哈顿最小生成树