POJ 2349 Arctic Network

题目链接:

http://poj.org/problem?id=2349

解题思路:

最小生成树问题,但是理解起来,非常费解。。。

用prim算法求解:

先求出每两个顶点之间的距离,(注意:是double类型的),然后用普里姆算法(Prim)求最小生成树。由于无线电的数目已给出m,需要把最小生成树分成m份,即删除m-1条边,得到m个连通分量。关键是删除哪些边呢,题目要求最小的D,故把构成最小生成树的边从大到小排序,删除前m-1条边,第m条边即所要求的最小D。

用kruskal算法求解:

P个哨所最多用P-1条边即可连起来,而S颗卫星可以代替S-1条边,基于贪心思想,代替的边越长,求得的D就越小。所以可以用一个数组保存加入最小生成树的边的长度,共有P-1条边,把前S-1条较长的边代替掉,剩下的边中最长的即为所求,即dis[(P-1) - (S-1) - 1] = dis[P-S-1]。

只要思路清晰,就可以很容易把这道题A了。

注意事项:

用g++交,用%.2f输出

用C++交,用%.2lf输出

不然会wrong。。。

AC代码(prim):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0xfffffff
using namespace std;

struct node{
    double x,y;
}no[505];
int s,p,ans;
double edge[505][505];
double dis[505];
double temp[505];
int vis[505];

double dist(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

bool cmp(double x,double y){
    return x > y;
}

void prim(int cur)
{
    int i, j, tmp;
    memset(vis, 0, sizeof(vis));
    for(i = 1; i <= p; i++)
        dis[i] = edge[cur][i];
    vis[cur] = 1;
    for(i = 2; i <= p; i++)
    {
        double Min = INF;
        for(j = 1; j <= p; j++)
        {
            if(!vis[j] && dis[j] < Min)
                Min = dis[tmp = j];
        }
        vis[tmp] = 1;
        temp[ans++] = Min;
        for(j = 1; j <= p; j++)
        {
            if(!vis[j] && dis[j] > edge[tmp][j])
                dis[j] = edge[tmp][j];
        }
    }
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&s,&p);
        for(int i = 1; i <= p; i++)
            scanf("%lf%lf",&no[i].x,&no[i].y);
        for(int i = 1; i <= p; i++){
            edge[i][i] = 0;
            for(int j = 1; j < i; j++){
                edge[i][j] = edge[j][i] = dist(no[i].x,no[i].y,no[j].x,no[j].y);
            }
        }
        ans = 0;
        prim(1);
        sort(temp,temp+ans,cmp);
        printf("%.2f\n",temp[s-1]);
    }
    return 0;
}


AC代码(kruskal):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0xfffffff
using namespace std;

struct node{
    double x,y;
}no[550];
int s,p,m,ans;
double dis[505];
int pa[505];

double dist(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

struct Edge
{
    int u,v;
    double w;
}edge[1000005];

bool cmp(Edge a,Edge b)
{
    return a.w < b.w;
}

int findset(int x)
{
    if(pa[x] != x)
        pa[x] = findset(pa[x]);
    return pa[x];
}

void kruskal()
{
    int i,u,v,cnt = p;
    for(i = 0; i < m; i++)
    {
        u = findset(edge[i].u);
        v = findset(edge[i].v);
        if(u != v)
        {
            dis[ans++] = edge[i].w;
            pa[v] = u;
            if(--cnt == 1)
                break;
        }
    }
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&s,&p);
        for(int i = 1; i <= p; i++)
            scanf("%lf%lf",&no[i].x,&no[i].y);
        m = 0;
        for(int i = 1; i <= p; i++)
            pa[i] = i;
        for(int i = 1; i <= p; i++){
            for(int j = 1; j <= i; j++){
                double tmp = dist(no[i].x,no[i].y,no[j].x,no[j].y);
                edge[m].u = i;
                edge[m].v = j;
                edge[m++].w = tmp;
                edge[m].u = j;
                edge[m].v = i;
                edge[m++].w = tmp;
            }
        }
        sort(edge,edge+m,cmp);
        ans = 0;
        kruskal();
        printf("%.2f\n",dis[p-s-1]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值