uva10369 最小生成树

题目大意:
南极有p个科研站, 要把这些站用卫星或者无线电连接起来,使得任意两个都能直接或者间接相连。任意两个都有安装卫星设备的,都可以直接通过卫星通信,不管它们距离有多远。 而安装有无线电设备的两个站,距离不能超过D。 D越长费用越多。
现在有s个卫星设备可以安装,还有足够多的无线电设备,求一个方案,使得费用D最少(D取决与所有用无线电通信的花费最大的那条路径)。

思路:
最小生成树问题,利用kruskal算法可以将前s个大的用卫星替代,那么这条路径上最大的花费就是第p - s大的花费。

代码:

kruskal算法

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
#include <cmath>
#include <algorithm>

int s,p;
double x[505],y[505];
int f[505];
double ans[505 * 505];
struct node {
    int u,v;
    double val;
}e[505 * 505];
int cmp(const node & a,const node & b) {
    return a.val < b.val;
}
int find(int x) {
    int i,j,k = x;
    while(k != f[k]) {
        k = f[k];
    }
    i = x;
    while(i != k) {
        j = f[i];
        f[i] = k;
        i = j;
    }
    return k;
}
bool Union(int m,int n) {
    int x = find(m);
    int y = find(n);
    if(x == y)
        return false;
    else {
        f[x] = y;
    }
    return true;
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%d %d",&s,&p);
        for(int i = 1 ; i <= p; i++) 
            scanf("%lf %lf",&x[i],&y[i]);
        int num = 0;
        for(int i = 1; i <= p; i++) {
            for(int j = i + 1; j <= p; j++) {
                e[num].u = i;
                e[num].v = j;
                e[num++].val = (sqrt)((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]));
            }
        }
        for(int i = 0; i <= p; i++) {
            f[i] = i;
        }
        sort(e, e + num, cmp);
        int k = 0;
        for(int i = 0; i < num; i++) {
            if(Union(e[i].u,e[i].v))
                ans[k++] = e[i].val;
        }
        printf("%.2lf\n",ans[k - s]);
    }
    return 0;
}

prim算法:

#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
#include <stdio.h>
#include <algorithm>

int h[505];
double x[505],y[505],w[505][505];
double ans[505 * 505];
int s,p;
double minCost[505];
int pre[505];
int t;
void Prim() {

    memset(h,0,sizeof(h));
    h[1] = 1;
    for(int i = 1; i <= p; i++)  {
        minCost[i] = w[1][i];
        pre[i] = 1;
    }
    int u = -1;
    t = 0;
    for(int i = 1; i < p; i++) {
        u = -1;
        for(int j = 1; j <= p; j++) {
            if(!h[j]) {
                if(u == -1 || minCost[j] < minCost[u])
                    u = j;
            }
        }
        ans[t++] = w[pre[u]][u];
        h[u] = 1;
        for(int j = 1; j <= p; j++) {
            if(!h[j] && minCost[j] > w[u][j]) {
                minCost[j] = w[u][j];
                pre[j] = u;
            }
        }
    }
    sort(ans,ans + t);
}
int main() {

    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%d %d",&s,&p);
        for(int i = 1; i <= p; i++)
            scanf("%lf %lf",&x[i],&y[i]);
        for(int i = 1; i <= p; i++) {
            for(int j = 1; j <= p; j++)
                w[i][j] = sqrt((x[i] - x[j]) *(x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
        }
        Prim();
        printf("%.2lf\n",ans[t - s]);
    }
    return 0;
}

你可能感兴趣的:(uva10369 最小生成树)