For a given point set P = {(xi, yi) : 1 i
n},
then construct a complete graph G = (V, E, W) with nvertexes. The weight function for any two vertexes is w(vi, vj)
= | xi - xj| + | yi - yj|. Please calculate the minimum spanning tree of G.
Hint
For the graph below, there exists a minimum spanning tree in which there is at most one vertex connected withA in the shadow area. You can extend this property to solve the problem.
Input
Input contains several cases.
Each cases begins with an integer n, 1 n
100,
000, to indicate the size of the point set. The points in the point set have serial numbers from 1 to n.
Each line of the following n lines contains two non-negative integers (xi, yi) (no more than 107) to describe the coordinate for each point. Any two points' coordinates are different.
The last case is followed by a line containing a zero.
Output
For each case, output the case's serial number and the weighted sum of all minimum spanning tree edges in the following format.Sample Input
3 0 0 2 0 0 3 0
Sample Output
Case 1: Total Weight = 5
题意:求曼哈顿最小生成树。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node
{
int x,y,pos;
}point[100010];
struct node2
{
int u,v,w;
}edge[40000010];
int T,t,n,N=40000020,tot,p[100010],c[40000020],d[40000020],INF=1e9;
bool cmp(node a,node b)
{
return a.x<b.x || (a.x==b.x && a.y<b.y);
}
bool cmp2(node2 a,node2 b)
{
return a.w<b.w;
}
int lowbit(int x)
{
return x&(-x);
}
int find(int x)
{
return x==p[x] ? x : p[x]=find(p[x]);
}
void query(int val,int w,int pos)
{
int id=-1,minn=INF,i;
val+=20000010;
for(i=val;i<N;i+=lowbit(i))
if(c[i]<minn)
{
minn=c[i];
id=d[i];
}
if(id!=-1)
{
tot++;
edge[tot].u=pos;
edge[tot].v=id;
edge[tot].w=minn-w;
}
}
void update(int val,int w,int pos)
{
int i,j,k;
val+=20000010;
for(i=val;i>0;i-=lowbit(i))
if(w<c[i])
{
c[i]=w;
d[i]=pos;
}
}
void go()
{
int i,j,k;
sort(point+1,point+1+n,cmp);
for(i=1;i<N;i++)
c[i]=INF;
for(i=n;i>=1;i--)
{
query(point[i].y-point[i].x,point[i].y+point[i].x,point[i].pos);
update(point[i].y-point[i].x,point[i].y+point[i].x,point[i].pos);
}
}
ll work()
{
int i,j,k,u,v;
ll ans=0;
tot=0;
go();
for(i=1;i<=n;i++)
swap(point[i].x,point[i].y);
go();
for(i=1;i<=n;i++)
point[i].y=-point[i].y;
go();
for(i=1;i<=n;i++)
swap(point[i].x,point[i].y);
go();
sort(edge+1,edge+1+tot,cmp2);
for(i=1;i<=n;i++)
p[i]=i;
for(i=1;i<=tot;i++)
{
u=find(edge[i].u);
v=find(edge[i].v);
if(u==v)
continue;
p[u]=v;
ans+=edge[i].w;
}
return ans;
}
int main()
{
int i,j,k;
ll ans;
while(~scanf("%d",&n) && n>0)
{
for(i=1;i<=n;i++)
{
scanf("%d%d",&point[i].x,&point[i].y);
point[i].pos=i;
}
ans=work();
printf("Case %d: Total Weight = %lld\n",++t,ans);
}
}