【POJ 3241】曼哈顿最小生成树(模板整理)

来源:互联网 发布:java web get post 编辑:程序博客网 时间:2024/06/08 11:32

关于 曼哈顿最小生成树 的证明见:http://www.2cto.com/kf/201505/399861.html

模板:

#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 100010;const int  INF = 0x3f3f3f3f;struct Point{    int x,y,id;}p[MAXN];bool cmp(Point a,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;    tot ++;}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 Manhattan_minimum_spanning_tree(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){    Manhattan_minimum_spanning_tree(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(){    int k;    while(scanf("%d%d",&n,&k) == 2 && n){        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;}


0 0
原创粉丝点击