求平面曼哈顿最小生成树第k大的边的长度模板
[POJ-3241] [Problem C]
const int maxn = 1e5+100;
const int INF = 0x3f3f3f3f;
struct point
{int x,y,id;
}p[maxn];
bool cmp(const point a,const point b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
struct BIT
{
int min_val,pos;
void init()
{
min_val=INF;
pos=-1;
}
}bit[maxn];
struct Edge
{int u,v,d;
}edge[maxn<<2];
bool cmpedge(Edge a,Edge b)
{
return a.d<b.d;
}
int tot;
int n;
int F[maxn];
int find(int x)
{
if(F[x]==-1)return x;
else return F[x]=find(F[x]);
}
void addedge(int u,int v,int d)
{
edge[tot].u=u;
edge[tot].v=v;
edge[tot++].d=d;
}
int lowbit(int x)
{
return x&-x;
}
void update(int i,int val,int pos)
{
while(i>0)
{
if(val<bit[i].min_val)
{
bit[i].min_val=val;
bit[i].pos=pos;
}
i-=lowbit(i);
}
}
int ask(int i,int m)
{
int min_val=INF,pos=-1;
while(i<=m)
{
if(bit[i].min_val<min_val)
{
min_val=bit[i].min_val;
pos=bit[i].pos;
}
i+=lowbit(i);
}
return pos;
}
int dist(point a,point b)
{
return abs(a.x-b.x)+abs(a.y-b.y);
}
void work(int n,point p[])
{
int a[maxn],b[maxn];
tot=0;
for(int dir=0;dir<4;dir++)
{
if(dir==1||dir==3)
{
for(int i=0;i<n;i++)
swap(p[i].x,p[i].y);
}
else if(dir==2)
{
for(int i=0;i<n;i++)
p[i].x=-p[i].x;
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
a[i]=b[i]=p[i].y-p[i].x;
sort(b,b+n);
int m=unique(b,b+n)-b;
for(int i=1;i<=m;i++)
bit[i].init();
for(int i=n-1;i>=0;i--)
{
int pos=lower_bound(b,b+m,a[i])-b+1;
int ans=ask(pos,m);
if(ans!=-1)
addedge(p[i].id,p[ans].id,dist(p[i],p[ans]));
update(pos,p[i].x+p[i].y,i);
}
}
}
int solve(int k)
{
work(n,p);
memset(F,-1,sizeof(F));
sort(edge,edge+tot,cmpedge);
for(int i=0;i<tot;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int t1=find(u),t2=find(v);
if(t1!=t2)
{
F[t1]=t2;
k--;
if(k==0)return edge[i].d;
}
}
}
int main(void)
{
int k;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y),p[i].id=i;
printf("%d\n",solve(n-k));
}
return 0;
}
求平面曼哈顿最小生成树的长度模板
[UVALive-3662] [Problem D]
typedef long long ll;
const int maxn = 1e5+100;
const int INF = 0x3f3f3f3f;
struct point
{int x,y,id;
}p[maxn];
bool cmp(const point a,const point b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
struct BIT
{
int min_val,pos;
void init()
{
min_val=INF;
pos=-1;
}
}bit[maxn];
struct Edge
{int u,v,d;
}edge[maxn<<2];
bool cmpedge(Edge a,Edge b)
{
return a.d<b.d;
}
int tot;
int n;
int F[maxn];
int find(int x)
{
if(F[x]==-1) return x;
else return F[x]=find(F[x]);
}
void addedge(int u,int v,int d)
{
edge[tot].u=u;
edge[tot].v=v;
edge[tot++].d=d;
}
int lowbit(int x)
{
return x&-x;
}
void update(int i,int val,int pos)
{
while(i>0)
{
if(val<bit[i].min_val)
{
bit[i].min_val=val;
bit[i].pos=pos;
}
i-=lowbit(i);
}
}
int ask(int i,int m)
{
int min_val=INF,pos=-1;
while(i<=m)
{
if(bit[i].min_val<min_val)
{
min_val=bit[i].min_val;
pos=bit[i].pos;
}
i+=lowbit(i);
}
return pos;
}
int dist(point a,point b)
{
return abs(a.x-b.x)+abs(a.y-b.y);
}
void work(int n,point p[])
{
int a[maxn],b[maxn];
tot=0;
for(int dir=0;dir<4;dir++)
{
if(dir==1||dir==3)
{
for(int i=0;i<n;i++)
swap(p[i].x,p[i].y);
}
else if(dir==2)
{
for(int i=0;i<n;i++)
p[i].x=-p[i].x;
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
a[i]=b[i]=p[i].y-p[i].x;
sort(b,b+n);
int m=unique(b,b+n)-b;
for(int i=1;i<=m;i++)
bit[i].init();
for(int i=n-1;i>=0;i--)
{
int pos=lower_bound(b,b+m,a[i])-b+1;
int ans=ask(pos,m);
if(ans!=-1)
addedge(p[i].id,p[ans].id,dist(p[i],p[ans]));
update(pos,p[i].x+p[i].y,i);
}
}
}
ll solve()
{
work(n,p);
memset(F,-1,sizeof(F));
ll res=0;
sort(edge,edge+tot,cmpedge);
for(int i=0;i<tot;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int t1=find(u),t2=find(v);
if(t1!=t2)
{
F[t1]=t2;
res+=edge[i].d;
}
}
return res;
}
int main(void)
{
int cas=1;
while(scanf("%d",&n)!=EOF,n)
{
for(int i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y),p[i].id=i;
printf("Case %d: Total Weight = %lld\n",cas++,solve());
}
return 0;
}
求平面曼哈顿最小生成树模板
最新推荐文章于 2018-07-25 16:01:00 发布