HDU 4081 Qin Shi Huang's National Road System

来源:互联网 发布:c语言控制机械手 编辑:程序博客网 时间:2024/05/16 18:49

题目大意:

        现有t个测例(t ≤ 10),每个测例都会给出n个点的坐标(2 < n ≤ 1,000),每个点的坐标信息形式诸如"X Y P",表示点的坐标为(X, Y),点权值为P,都为整型,其中0 ≤ X, Y ≤ 1,000,0 < P < 100,000,现要求n - 1条边将所有n个点都连通,并且将其中一条边的权值变为0,现要使变为0的边的两点的权值之和比上其它边权值之和最大,该如何构造这n - 1条以及如何挑选变为0的边才能是该比值最大,要求对于每个测例都输出该最大值,保留两位小数(边长即为两点的欧几里得距离)。

题目链接

注释代码:

/*                                   * Problem ID : HDU 4081 Qin Shi Huang's National Road System * Author     : Lirx.t.Una                                   * Language   : C++                       * Run Time   : 171 ms                                   * Run Memory : 18200 KB                                  */#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <queue>//思路://先求MST使得n个点连通且边数为n - 1,并且使得总边权尽可能小//这也使得点权比边权尽可能大//然后在挑选边变为0测试ratio的大小,但是最小生成树可能有多个//本来边(i, j)不在当前MST中,但是有可能在另一个MST中//因此需要通过max_seg[i][j]换边得到另一种最小生成树//但是g[i][j]并不一定等于max_seg[i][j],但是没有关系//因为即使替换了也要将其边权变为0,就相当于将两点合为一点,因此没有关系//因此最后逐个检查图中的每条边g[i][j],如果g[i][j]是当前MST中的点则非0边权为总边权减去g[i][j]//否则非0边权就是总边权减去max_seg[i][j]//最大点数#define    MAXN    1000using namespace std;struct    Point {//每个点的坐标以及点权值    int        x, y;    int        w;    friend istream &    operator>>(istream &is, Point &p) {            is >> p.x >> p.y >> p.w;        return is;    }    int    POW(int a) { return a * a; }    double    operator^(Point &oth) {            return sqrt((double)( POW( x - oth.x ) + POW( y - oth.y ) ));    }};struct    Node {//Prim堆优化中的结点    int       u;    double    d;    Node(void) {}    Node( int uu, double dd ) : u(uu), d(dd) {}    bool    operator<(const Node &oth)    const {            return d > oth.d;    }};double        max_seg[MAXN + 1][MAXN + 1];double        g[MAXN + 1][MAXN + 1];double        d[MAXN + 1];Point    p[MAXN + 1];//表示每个点int        pre[MAXN + 1];bool    vis[MAXN + 1];bool    mst[MAXN + 1][MAXN + 1];inline doublemax( double a, double b ) {    return a > b ? a : b;}double//返回最小生成树的总边权prim(int n) {    int        i;    int        u, v;    int        nv;    double    ans;    Node    node;    priority_queue<Node>    heap;    memset(vis, 0, sizeof(vis));    memset(mst, 0, sizeof(mst));    memset(max_seg, -1, sizeof(max_seg));    vis[1] = true;    for ( i = 2; i <= n; i++ ) {            d[i]   = g[1][i];        pre[i] = 1;        heap.push(Node( i, d[i] ));    }    ans = 0.0;    nv  = 1;    while (true) {//完全图必定有解,无需判断            while (true) {//必定有解                    node = heap.top();            heap.pop();            if ( !vis[ u = node.u ] ) {                            nv++;                ans += node.d;                mst[ pre[u] ][u] = true;                mst[u][ pre[u] ] = true;                for ( i = 1; i <= n; i++ )                    if ( vis[i] ) {                                            max_seg[i][u] = max( max_seg[i][ pre[u] ], node.d );                        max_seg[u][i] = max_seg[i][u];                    }                vis[u] = true;                break;            }        }        if ( nv == n ) break;        for ( v = 2; v <= n; v++ )            if ( !vis[v] && g[u][v] < d[v] ) {                            d[v]   = g[u][v];                pre[v] = u;                heap.push(Node( v, d[v] ));            }    }    return ans;}intmain() {    int        t;    int        n;    int        i, j;    double    B;//MST边的总权值    double    r;//最后的比例    scanf("%d", &t);    while ( t-- ) {            scanf("%d", &n);        for ( i = 1; i <= n; i++ ) cin >> p[i];        for ( i = 1; i <= n; i++ )            for ( j = i + 1; j <= n; j++ ) {                            g[i][j] = p[i] ^ p[j];                g[j][i] = g[i][j];            }        r = -1.0;//初始化为一个极小值        B = prim(n);        for ( i = 1; i <= n; i++ )            for ( j = i + 1; j <= n; j++ )                if ( mst[i][j] )//MST中的边之间边为0试一下                    r = max( r, ( p[i].w + p[j].w ) / ( B - g[i][j] ) );                else//非MST中的边g[i][j]替换max_seg[i][j]再变为0试一下                    r = max( r, ( p[i].w + p[j].w ) / ( B - max_seg[i][j] ) );        printf("%.2lf\n", r);    }            return 0;}
无注释代码:

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <queue>#define    MAXN    1000using namespace std;struct    Point {    int        x, y;    int        w;    friend istream &    operator>>(istream &is, Point &p) {            is >> p.x >> p.y >> p.w;        return is;    }    int    POW(int a) { return a * a; }    double    operator^(Point &oth) {            return sqrt((double)( POW( x - oth.x ) + POW( y - oth.y ) ));    }};struct    Node {    int        u;    double    d;    Node(void) {}    Node( int uu, double dd ) : u(uu), d(dd) {}    bool    operator<(const Node &oth)    const {            return d > oth.d;    }};double        max_seg[MAXN + 1][MAXN + 1];double        g[MAXN + 1][MAXN + 1];double        d[MAXN + 1];Point    p[MAXN + 1];int        pre[MAXN + 1];bool    vis[MAXN + 1];bool    mst[MAXN + 1][MAXN + 1];inline doublemax( double a, double b ) {    return a > b ? a : b;}doubleprim(int n) {    int        i;    int        u, v;    int        nv;    double    ans;    Node    node;    priority_queue<Node>    heap;    memset(vis, 0, sizeof(vis));    memset(mst, 0, sizeof(mst));    memset(max_seg, -1, sizeof(max_seg));    vis[1] = true;    for ( i = 2; i <= n; i++ ) {            d[i]   = g[1][i];        pre[i] = 1;        heap.push(Node( i, d[i] ));    }    ans = 0.0;    nv    = 1;    while (true) {            while (true) {                    node = heap.top();            heap.pop();            if ( !vis[ u = node.u ] ) {                            nv++;                ans += node.d;                mst[ pre[u] ][u] = true;                mst[u][ pre[u] ] = true;                for ( i = 1; i <= n; i++ )                    if ( vis[i] ) {                                            max_seg[i][u] = max( max_seg[i][ pre[u] ], node.d );                        max_seg[u][i] = max_seg[i][u];                    }                vis[u] = true;                break;            }        }        if ( nv == n ) break;        for ( v = 2; v <= n; v++ )            if ( !vis[v] && g[u][v] < d[v] ) {                            d[v]   = g[u][v];                pre[v] = u;                heap.push(Node( v, d[v] ));            }    }    return ans;}intmain() {    int        t;    int        n;    int        i, j;    double    B;    double    r;    scanf("%d", &t);    while ( t-- ) {            scanf("%d", &n);        for ( i = 1; i <= n; i++ ) cin >> p[i];        for ( i = 1; i <= n; i++ )            for ( j = i + 1; j <= n; j++ ) {                            g[i][j] = p[i] ^ p[j];                g[j][i] = g[i][j];            }        r = -1.0;        B = prim(n);        for ( i = 1; i <= n; i++ )            for ( j = i + 1; j <= n; j++ )                if ( mst[i][j] )                     r = max( r, ( p[i].w + p[j].w ) / ( B - g[i][j] ) );                else                    r = max( r, ( p[i].w + p[j].w ) / ( B - max_seg[i][j] ) );        printf("%.2lf\n", r);    }            return 0;}

0 0