zoukankan      html  css  js  c++  java
  • poj 3241 Object Clustering 曼哈顿最小生成树

    题意:

           平面上有n个点,如今把他们分成k个集合。使得每一个集合中的每一个点都至少有一个本集合的点之间的曼哈顿距离不大于X,求最小的X。

    分析:

           转化为求n个点生成全然图的最小生成树的第k大边。接下来有几个重点。

    1)依据莫队算法。因为边权是点的曼哈顿距离,每一个点仅仅须要跟周围8个方向中每一个方向近期的点连边。这样算出的图与用全然图算出的最小生成树一样。涉及的边却大大降低。

    2)用树状数组维护y右偏45度的近期点,每一个点以y-x的位置,y+x的值放入树状数组。因为每次是查询区间(pos,last)的情况,所以树状数组c[i]的覆盖范围要改成a[i,i+1,...a+2^k-1],k是i二进制末尾0的个数。查询和更新也有对应修改。

    3)对最小生成树一个猜想:设一个图的最小生成树的各边按权从小到大排序为a1,a2....an-1,该图随意生成树的各边按权从小到大排序为b1,b2,..bn-1,则ai<=bi(i=1,2,...n-1)。

    代码:

    //poj 3241
    //sep9
    #include <iostream>
    #include <algorithm>
    const int maxN=10024;
    using namespace std;
    int n,k,e;
    struct P
    {
    	int x,y,ids;
    }p[maxN];
    struct EDGE
    {
    	int u,v,w;		
    }edge[maxN*4];
    int c[4000],d[4000],fa[maxN];
    
    int lowbit(int x)
    {
    	return x&(x^(x-1));
    }
    
    int cmp_p(P a,P b)
    {
    	if(a.x!=b.x)
    		return a.x<b.x;
    	return a.y<b.y;	
    }
    
    int cmp_e(EDGE a,EDGE b)
    {
    	return a.w<b.w;
    }
    void query(int ids,int pos,int val)
    {
    	pos+=1000;
    	int t_ids=-1,ret=INT_MAX;
    	for(int i=pos;i<4000;i+=lowbit(i))
    		if(ret>c[i]){
    			ret=c[i];
    			t_ids=d[i];
    		}
    	if(t_ids!=-1){
     		edge[e].u=ids;
    		edge[e].v=t_ids;
    		edge[e++].w=ret-val;
    	}
    }
    
    void update(int ids,int pos,int val)
    {
    	pos+=1000;
    	for(int i=pos;i;i-=lowbit(i))
    		if(val<c[i]){
    			c[i]=val;
    			d[i]=ids;
    		}
    }
    
    void deal()
    {
    	memset(c,63,sizeof(c));
    	sort(p,p+n,cmp_p);	
    	for(int i=n-1;i>=0;--i){
    		int pos=p[i].y-p[i].x;
    		int val=p[i].y+p[i].x;
    		query(p[i].ids,pos,val);
    		update(p[i].ids,pos,val);
    	}
    }
    int find(int x)
    {
    	return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    
    int solve()
    {
    	if(n==k)
    		return 0;
    	e=0;
    	deal();
    	for(int i=0;i<n;++i)
    		swap(p[i].x,p[i].y);
    	deal();
    	for(int i=0;i<n;++i)
    		p[i].y=-p[i].y;
    	deal();
    	for(int i=0;i<n;++i)
    		swap(p[i].x,p[i].y);
    	deal();
    	for(int i=0;i<n;++i) fa[i]=i;
    	sort(edge,edge+e,cmp_e);
    	for(int i=0;i<e;++i){
    		int pa=find(edge[i].u);
    		int pb=find(edge[i].v);
    		if(pa!=pb){
    			fa[pa]=pb;
    			n--;
    			if(n==k)
    				return edge[i].w;
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&k);
    	for(int i=0;i<n;++i){
    		scanf("%d%d",&p[i].x,&p[i].y);
    		p[i].ids=i;
    	}
    	printf("%d",solve());			
    } 

     

  • 相关阅读:
    TableDriven method code complete reading notes
    Fundamental data type Code complete reading notes(12)
    利用消息机制实现.NET AOP(面向方面编程)--利用RealProxy和消息接收器实现多截获
    Organizing straightline code Code complete reading notes(14)
    Statements Code complete reading notes
    The softwarequanlity landscape Code complete reading notes
    支持ViewState和ControlState压缩的页面基类(ASP.NET2.0)
    XPath遇上命名空间
    怎样让WinForms下DataGrid可以像ASP.NET下的DataGrid一样使用自定义的模板列
    检验密码强度的JS类
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5375000.html
Copyright © 2011-2022 走看看