最小生成树 Kruskal

Kruskal适用于点比较多边比较少的情况(稀疏图)

HDU 1875 畅通工程再续

#include <cstdio>
#include <cmath>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;

const int MAXN = 1000 + 5;
const double eps = 0;

int fa[MAXN];

struct point {
    double x, y;
}p[MAXN];

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

struct edge {
    int u, v;
    double w;
    bool operator < (const edge &rhs) const {
        return w < rhs.w;
    }
} e[MAXN * MAXN];

int findfa(int u) {
    if (fa[u] != u) fa[u] = findfa(fa[u]);
    return fa[u];
}

int m;
double cost;

void unin(int u, int v, double w) {
    int fau = findfa(u);
    int fav = findfa(v);
    if (fau == fav) return;
    if (fau < fav) {
        fa[fav] = fau;
    } else {
        fa[fau] = fav;
    }
    cost += w;
    m--;
}

int main() {
    //freopen("in.txt", "r", stdin);
    int n, t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }

        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                e[cnt].u = i;
                e[cnt].v = j;
                e[cnt++].w = dis(i, j);
            }
        }

        sort(e, e + cnt);
        m = n - 1, cost = 0;
        for (int i = 0; i < cnt; i++) {
            if (m == 0) break;
            //if (e[i].w < 10 || e[i].w  > 1000) continue;
            if (e[i].w - 10 < eps || e[i].w - 1000 > eps) continue;
            unin(e[i].u, e[i].v, e[i].w);
        }

        if (!m) printf("%.1f\n", cost * 100.0);
        else puts("oh!");
    }
    return 0;
}

HDU 4081 Qin Shi Huang’s National Road System

给出一个图,每个节点是一个城市,权值代表人口,城市间的距离里为欧基里德距离。现在求这个图的一个生成树,使A/B尽可能的大,其中A是生成树的某条边的两个节点上人口数的和,B是这个生成树上除了刚才选中的那条边之外的所有边的距离的和

要B尽可能的小,先求原图的一个最小生成树,要添加一条边并替换最小生成树上的某一条边,使它仍是一个树。枚举要添加的边,维护一个A/B的最大值,即可求出答案,如果这条边是原生成树上的边,设原来的最小生成树上的边权和为EW,则B = EW – e[i].w; 如果要添加的边不是原来最小生成树上的边,B = EW – maxd[e[i].u][e[i].v],maxd[i][j]表示在生成树上从i点到j点路上最长边的值

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;

const int MAXN = 1000 + 50;
int tot, cnt, n;

int head[MAXN], fa[MAXN], vis[MAXN];
double maxd[MAXN][MAXN];
bool G[MAXN][MAXN];

struct Edge{
    int u, v;
    double w;
    bool operator < (const Edge &rhs) const {
        return w < rhs.w;
    }
}E[MAXN * MAXN];

struct edge{
    int to, nxt;
    double cost;
}e[MAXN << 2];

void init() {
    tot = 0, cnt = 0;
    memset(head, -1, sizeof(head));
    memset(maxd, 0, sizeof(maxd));
    memset(G, 0, sizeof(G));
}

void addedge(int u, int v, double w) {
    e[tot].to = v;
    e[tot].cost = w;
    e[tot].nxt = head[u];
    head[u] = tot++;
}

struct point {
    int x, y;
    double w;
}p[MAXN];

void bfs(int s) {
    queue<int>q;
    memset(vis, 0, sizeof(vis));
    vis[s] = 1;
    q.push(s);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = head[u]; i != -1; i = e[i].nxt) {
            int v = e[i].to;
            if (vis[v]) continue;
            maxd[s][v] = maxd[v][s] = max(maxd[s][u], e[i].cost);
            q.push(v);
            vis[v] = 1;
        }
    }
}

void dfs(int rt, int u, int fa, double md) {
    for (int i = head[u]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if (v == fa) continue;
        maxd[rt][v] = maxd[v][rt] = max(md, e[i].cost);
        dfs(rt, v, u, maxd[rt][v]);
    }
}

int findfa(int u) {
    if (fa[u] != u) fa[u] = findfa(fa[u]);
    return fa[u];
}

double kru(int n) {
    int m = n - 1;
    double ew = 0;
    for (int i = 0; i <= n; i++) fa[i] = i;
    sort(E, E + cnt);
    for (int i = 0; i < cnt; i++) {
        int u = E[i].u, v = E[i].v;
        double  w = E[i].w;
        int fau = findfa(u);
        int fav = findfa(v);
        if (fau == fav) continue;
        if (fau > fav) swap(fau, fav);
        fa[fav] = fau;
        ew += E[i].w;
        addedge(u, v, w);
        addedge(v, u, w);
        G[u][v] = G[v][u] = 1;
        if(--m <= 0) break;
    }
    return ew;
}

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

int main() {
    //freopen("in.txt", "r", stdin);
    int t;
    scanf("%d", &t);
    while (t--) {
        init();
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d%d%lf", &p[i].x, &p[i].y, &p[i].w);

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i == j) continue;
                E[cnt].u = i;
                E[cnt].v = j;
                E[cnt++].w = dis(i, j);
            }
        }

        double ew = kru(n);
        //for (int i = 1; i <= n; i++) dfs(i, i, -1, 0);
        for (int i = 1; i <= n; i++) bfs(i);

        double ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                ans = max(ans, (p[i].w + p[j].w) / (ew - maxd[i][j]));
            }
        }
        printf("%.2f\n", ans);
    }
    return 0;
}

results matching ""

    No results matching ""