UVALive 3662Another Minimum Spanning Tree 曼哈顿最小距离生成树

来源:互联网 发布:u盘坏了如何恢复数据 编辑:程序博客网 时间:2024/05/01 02:48

题目:http://acm.hust.edu.cn/vjudge/problem/23379

题意:平面上有n个点,求这些点的曼哈顿最小距离生成树。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#include <cmath>using namespace std;typedef long long ll;const int N = 100010;const int INF = 0x3f3f3f3f;struct node{    int x, y, id;}p[N];struct edge{    int v, u, d;}g[N*10];struct BIT{    int minn, pos;    void init()    {        minn = INF, pos = -1;    }}bit[N];int n, k, tot, cas;int par[N];bool cmp(node a, node b){    if(a.x != b.x) return a.x < b.x;    else return a.y < b.y;}int ask(int i, int m){    int minn = INF, pos = -1;    while(i <= m)    {        if(bit[i].minn < minn)            minn = bit[i].minn, pos = bit[i].pos;        i += i & -i;    }    return pos;}void update(int i, int val, int pos){    while(i > 0)    {        if(val < bit[i].minn)            bit[i].minn = val, bit[i].pos = pos;        i -= i & -i;    }}void add_edge(int v, int u, int d){    g[tot].v = v, g[tot].u = u, g[tot++].d = d;}bool cmpg(edge a, edge b){    return a.d < b.d;}int ser(int x){    int r = x, i = x, j;    while(r != par[r]) r = par[r];    while(par[i] != r) j = par[i], par[i] = r, i = j;    return r;}void mmst(int n, node p[]){    int a[N], b[N];    tot = 0;    for(int i = 0; i < 4; i++)    {        if(i == 1 || i == 3)        {            for(int j = 0; j < n; j++)                swap(p[j].x, p[j].y);        }        else if(i == 2)        {            for(int j = 0; j < n; j++)                p[j].x = -p[j].x;        }        sort(p, p + n, cmp);        for(int j = 0; j < n; j++)            a[j] = b[j] = p[j].y - p[j].x;        sort(b, b + n);        int m = unique(b, b + n) - b;        for(int j = 1; j <= m; j++)            bit[j].init();        for(int j = n - 1; j >= 0; j--)        {            int pos = lower_bound(b, b + m, a[j]) - b + 1;            int ans = ask(pos, m);            if(ans != -1)                add_edge(p[j].id, p[ans].id, abs(p[j].x - p[ans].x) + abs(p[j].y - p[ans].y));            update(pos, p[j].x + p[j].y, j);        }    }}void solve(){    mmst(n, p);    for(int i = 0; i < n; i++) par[i] = i;    sort(g, g + tot, cmpg);    ll res = 0;    for(int i = 0; i < tot; i++)    {        int fv = ser(g[i].v), fu = ser(g[i].u);        if(fv != fu)        {            par[fu] = fv;            res += g[i].d;        }    }    printf("Case %d: Total Weight = %lld\n", ++cas, res);}int main(){    while(scanf("%d", &n), n)    {        for(int i = 0; i < n; i++)            scanf("%d%d", &p[i].x, &p[i].y), p[i].id = i;        solve();    }    return 0;}


0 0