您的位置:首页 > 其它

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

2014-07-29 15:28 337 查看

畅通工程再续

[b]Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 14590    Accepted Submission(s): 4497
[/b]

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

 

[align=left]Input[/align]
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。

每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。

 

 

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

 

[align=left]Sample Input[/align]

2
2
10 10
20 20
3
1 1
2 2
1000 1000

 

 

[align=left]Sample Output[/align]

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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU1875