Uva 10369 (最小生成树)

题意:

有 P 个哨站, 哨站之间用 无线电传播。
现在有 S 个卫星, 一个卫星可以连接任意两个哨站。
无线电的最长传播距离为 D。
现在 P 个哨站的坐标, 要求每个哨站之间至少有一条通信通道;
求D 的最小值。

分析:

先把 P 个哨站看成P 个点,这里总共有 P(P1)2 条边的图;
边权就是距离。
在没有卫星的情况下, 所有无线电的在满足至少一条的情况下就是这个
图的最小生成树。 现在有了距离限制, S 个卫星可以代替最小生成树的 S 条边。
现在要使得 P 最小, 就把最小生成树中前 S 大的边删掉就可以了。

Code:

#include 
using namespace std;
const int maxn = 500 + 7;
//UF 并查集
int pre[maxn],Cnt[maxn];
void INIT(int n) {
    for(int i = 0; i <= n; ++i)
        pre[i] = i, Cnt[i] = 1;
}

int Find(int x) {
    if(x != pre[x]) 
        return pre[x] = Find(pre[x]);
    else return x;
}

bool Union(int x, int y) {
    int xx = Find(x), yy = Find(y);
    if(xx == yy) return false;
    if(Cnt[xx] < Cnt[yy]) {
        Cnt[yy] += Cnt[xx];
        pre[xx] = yy;
    } else {
        Cnt[xx] += Cnt[yy];
        pre[yy] = xx;
    }
    return true;
}

//Ks 最小生成树
int NodeX[maxn], NodeY[maxn];
struct Edge {
    int u, v;
    double dist;
    Edge() {}
    Edge(int U, int V, int Ux, int Uy, int Vx, int Vy) {
        u = U, v = V;
        dist = sqrt((Ux-Vx)*(Ux-Vx) + (Uy-Vy)*(Uy-Vy));
    }
    bool operator < (const Edge a) const {
        return dist < a.dist;
    }
};
Edge E[maxn * maxn];
int cnt, P, S;
vector<double> Dits;
double Ksul() {
    Dits.clear();
    for(int i = 0; i < cnt; ++i) {
        if(Union(E[i].u, E[i].v)) {
            Dits.push_back(E[i].dist);
        }
    }
    return Dits[Dits.size()-S];
}

int main() {
    int T;
    scanf("%d",&T);
    for(int kase = 1; kase <= T; ++kase) {
        scanf("%d%d",&S, &P);
        INIT(P);
        for(int i = 0; i < P; ++i) {
            scanf("%d%d",NodeX+i, NodeY+i);
        }
        cnt = 0;
        for(int i = 0; i < P; ++i) {
            for(int j = i+1; j < P; ++j) {
                E[cnt++] = Edge(i,j,NodeX[i],NodeY[i],NodeX[j],NodeY[j]);
            }
        }
        sort(E,E+cnt);
        printf("%.2f\n", Ksul());
    }
    return 0;
}

你可能感兴趣的:(图论)