现在的位置: 首页 > 综合 > 正文

HDU1875 畅通工程再续 【最小生成树Prim】

2015年12月04日 ⁄ 综合 ⁄ 共 3572字 ⁄ 字号 评论关闭

畅通工程再续

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 14590    Accepted Submission(s): 4497

Problem Description
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
 

 

Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
 

 

Output
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
 

 

Sample Input
2 2 10 10 20 20 3 1 1 2 2 1000 1000
 

 

Sample Output
1414.2 oh!

 

这题的陷阱是注意浮点数。

2014.8.17更新:31ms prim

#include <stdio.h>
#include <string.h>
#include <math.h>
#define maxn 102
#define maxm (maxn * maxn) >> 1
#define inf 0x3f3f3f3f

struct Node2{
    int x, y;
} V[maxn];
struct Node{
    int u, v;
    double d;
} E[maxm];
double ans, dist[maxn], map[maxn][maxn];
bool vis[maxn];

double calDist(int i, int j)
{
    double x = V[i].x - V[j].x;
    double y = V[i].y - V[j].y;
    return sqrt(x * x + y * y);
}

int getNext(int n)
{
    int u = -1, i;
    double tmp = inf;
    for(i = 1; i <= n; ++i)
        if(!vis[i] && dist[i] < tmp){
            tmp = dist[i]; u = i;
        }
    return u;
}

bool Prim(int n)
{
    int i, u, v, count = 0;
    double tmp; ans = 0.0;
    for(i = 1; i <= n; ++i){
        vis[i] = 0; dist[i] = inf;
        if(map[1][i] >= 10.0 && map[1][i] <= 1000.0)
            dist[i] = map[1][i];
    }
    u = 1; dist[u] = 0.0; vis[u] = 1;
    u = getNext(n);
    while(count < n - 1){
        if(u == -1) return false;
        vis[u] = 1; ans += dist[u]; ++count;
        for(i = 1; i <= n; ++i)
            if(!vis[i] && map[u][i] <= 1000.0 && map[u][i] >= 10.0 && dist[i] > map[u][i]){
                dist[i] = map[u][i];
            }        
        u = getNext(n);
    }
    return true;
}

int main()
{
    int t, n, i, j;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        for(i = 1; i <= n; ++i)
            scanf("%d%d", &V[i].x, &V[i].y);
        for(i = 1; i < n; ++i)
            for(j = i + 1; j <= n; ++j)
                map[i][j] = map[j][i] = calDist(i, j);
        if(!Prim(n)) printf("oh!\n");
        else printf("%.1lf\n", ans * 100.0);
    }
}

Kruskal:140ms

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define maxn 102
#define maxm (maxn * maxn) >> 1
using std::sort;

int pre[maxn], count, id;
struct Node2{
    int x, y;
} V[maxn];
struct Node{
    int u, v;
    double d;
} E[maxm];
double ans;

int ufind(int k)
{
    int a = k, b;
    while(pre[k] != -1) k = pre[k];
    while(a != k){
        b = pre[a];
        pre[a] = k;
        a = b;
    }
    return k;
}

bool cmp(Node a, Node b){
    return a.d < b.d;
}

double calDist(int i, int j)
{
    double x = V[i].x - V[j].x;
    double y = V[i].y - V[j].y;
    return sqrt(x * x + y * y);
}

bool Kruskal(int n, int m)
{
    ans = 0;
    int i, u, v;
    for(i = 0; i < m; ++i){
        u = ufind(E[i].u);
        v = ufind(E[i].v);
        if(u != v && E[i].d >= 10 && E[i].d <= 1000){
            ans += E[i].d; pre[v] = u;
            if(--count == 1) return true;
        }
    }
    return 1 == count;
}

int main()
{
    int t, n, i, j;
    scanf("%d", &t);
    while(t--){
        memset(pre, -1, sizeof(pre));
        scanf("%d", &n);
        count = n;
        for(i = 1; i <= n; ++i)
            scanf("%d%d", &V[i].x, &V[i].y);
        for(i = 1, id = 0; i < n; ++i)
            for(j = i + 1; j <= n; ++j){
                E[id].u = i; E[id].v = j;
                E[id++].d = calDist(i, j);
            }
        sort(E, E + id, cmp);
        if(!Kruskal(n, id)) printf("oh!\n");
        else printf("%.1lf\n", ans * 100.0);
    }
}

更新前: 328ms Prim

#include <stdio.h>
#include <string.h>
#include <math.h>
#define maxn 102

double map[maxn][maxn];
bool vis[maxn];
struct Node{
    int x, y;
} arr[maxn];

double cal(Node a, Node b)
{
    double x = a.x - b.x, y = a.y - b.y;
    return sqrt(x * x + y * y);
}

void Prim(int n)
{
    int u, i, j, count = 0;
    double len = 0, tmp;
    vis[0] = 1;
    while(count < n - 1){
        for(i = 0, tmp = -1; i < n; ++i){
            if(!vis[i]) continue;
            for(j = 0; j < n; ++j){
                if(map[i][j] >= 0 && !vis[j] && (map[i][j] < tmp || tmp < 0)){
                    tmp = map[i][j]; u = j;
                }
            }
        }
        if(tmp > 0){
            ++count; vis[u] = 1;
            len += tmp * 100;
        }else break;
    }
    if(count == n - 1) printf("%.1lf\n", len);
    else printf("oh!\n");
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int t, n, a, b, i, j;
    double len;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        memset(vis, 0, sizeof(vis));
        for(i = 0; i <= n; ++i)
            for(j = 0; j <= n; ++j) map[i][j] = -1;
        for(i = 0; i < n; ++i){
            scanf("%d%d", &arr[i].x, &arr[i].y);
            for(j = 0; j < i; ++j){
                len = cal(arr[i], arr[j]);
                if(len >= 10.0 && len <= 1000.0){
                    if(map[i][j] < 0 || len < map[i][j])
                        map[i][j] = map[j][i] = len;
                }
            }
        }
        Prim(n);
    }
    return 0;
}

 

抱歉!评论已关闭.