poj 3241 http://poj.org/problem?id=3241
求曼哈顿距离最小生成树第K长的边的长度
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 100010
#define MAXM 100010
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
int Read()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
int x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
void Print(int a)
{
if(a>9)
Print(a/10);
putchar(a%10+'0');
}
struct Point
{
int x,y,id;
}p[MAXN];
bool cmp(Point a,Point b)
{
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
//树状数组 找y-x大于当前的 但是y+x最小的
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);
}
}
//查询[i,m]的最小值位置
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 Manhattan_minmum_spanning_tree(int n,Point p[])
{
int a[MAXN],b[MAXN];
tot=0;
for(int dir=0;dir<4;dir++)
{
//4种坐标变换
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)
{
Manhattan_minmum_spanning_tree(n,p);
MEM(F,-1);
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()
{
// fread;
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 http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23379
求曼哈顿距离最小生成树中边的权值和
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 100010
#define MAXM 100010
#define INF 99999999
#define ll long long
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
int Read()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
int x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
void Print(int a)
{
if(a>9)
Print(a/10);
putchar(a%10+'0');
}
struct Point
{
int x,y,id;
}p[MAXN];
bool cmp(Point a,Point b)
{
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
//树状数组 找y-x大于当前的 但是y+x最小的
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);
}
}
//查询[i,m]的最小值位置
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 Manhattan_minmum_spanning_tree(int n,Point p[])
{
int a[MAXN],b[MAXN];
tot=0;
for(int dir=0;dir<4;dir++)
{
//4种坐标变换
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()
{
Manhattan_minmum_spanning_tree(n,p);
MEM(F,-1);
sort(edge,edge+tot,cmpedge);
ll ans=0;
for(int i=0;i<tot;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int t1=find(u),t2=find(v);
int k=0;
if(t1!=t2)
{
F[t1]=t2;
ans+=(ll)edge[i].d;
// k++;
// if(k==n-1)
// break;//加上也可以。。。
}
}
return ans;
}
int main()
{
// fread;
int cs=1;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
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 = ",cs++);
printf("%lld\n",solve());
}
return 0;
}