最小生成树

繁华的都市

这是一个**最小生成树(MST)**问题,要求:

1.连接所有节点(连通图)

2.边数最少 → 正好是 n−1 条(生成树)

3.在满足前两条下,最大边权最小 → 最小生成树中的最大边权

算法思路:

1.使用 Kruskal 或 Prim 求最小生成树。

2.Kruskal 按边权从小到大排序,用并查集维护连通性。

3.生成树中的最大边权就是答案。

注意:输出格式要求输出两个整数:选出的边数 和 最大边权。

1.边数一定是 n−1(因为保证连通)。

2.最大边权是生成树中最大的边权。

cs 复制代码
#include <stdio.h>
#include <stdlib.h>

#define MAX_N 305
#define MAX_M 100005

typedef struct {
    int u, v, w;
} Edge;

Edge edges[MAX_M];
int parent[MAX_N];

// 并查集:查找根
int find(int x) {
    if (parent[x] != x)
        parent[x] = find(parent[x]);
    return parent[x];
}

// 并查集:合并
void union_set(int x, int y) {
    int rx = find(x);
    int ry = find(y);
    if (rx != ry)
        parent[rx] = ry;
}

// 比较函数,用于排序
int cmp(const void* a, const void* b) {
    Edge* e1 = (Edge*)a;
    Edge* e2 = (Edge*)b;
    return e1->w - e2->w;
}

int main() {
    int n, m;
    scanf("%d %d", &n, &m);

    for (int i = 0; i < m; i++) {
        scanf("%d %d %d", &edges[i].u, &edges[i].v, &edges[i].w);
    }

    // 按权值排序
    qsort(edges, m, sizeof(Edge), cmp);

    // 初始化并查集
    for (int i = 1; i <= n; i++) {
        parent[i] = i;
    }

    int edge_count = 0;
    int max_weight = 0;

    // Kruskal
    for (int i = 0; i < m; i++) {
        int u = edges[i].u;
        int v = edges[i].v;
        int w = edges[i].w;

        if (find(u) != find(v)) {
            union_set(u, v);
            edge_count++;
            if (w > max_weight)
                max_weight = w;
        }
        if (edge_count == n - 1)
            break;
    }

    printf("%d %d\n", edge_count, max_weight);
    return 0;
}

城市规划大师

cs 复制代码
#include <stdio.h>
#include <stdlib.h>

#define MAXN 1005
#define MAXM (MAXN * MAXN)   // 完全图边数

typedef struct {
    int u, v, w;
} Edge;

Edge edges[MAXM];
int parent[MAXN];
int ban[MAXN][MAXN];  // 禁止边标记

int n, k;
int x[MAXN], y[MAXN];
int edge_cnt = 0;

int abs(int a) { return a < 0 ? -a : a; }
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

// 曼哈顿距离
int manhattan(int i, int j) {
    return abs(x[i] - x[j]) + abs(y[i] - y[j]);
}

int cmp(const void* a, const void* b) {
    return ((Edge*)a)->w - ((Edge*)b)->w;
}

int find(int x) {
    if (parent[x] != x)
        parent[x] = find(parent[x]);
    return parent[x];
}

void union_set(int x, int y) {
    int rx = find(x);
    int ry = find(y);
    if (rx != ry)
        parent[rx] = ry;
}

int main() {
    scanf("%d %d", &n, &k);
    
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &x[i], &y[i]);
    }
    
    // 初始化禁止边
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            ban[i][j] = 0;
    
    for (int i = 0; i < k; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        ban[u][v] = 1;
        ban[v][u] = 1;
    }
    
    // 生成所有允许的边
    edge_cnt = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            if (ban[i][j]) continue;  // 禁止边跳过
            edges[edge_cnt].u = i;
            edges[edge_cnt].v = j;
            edges[edge_cnt].w = manhattan(i, j);
            edge_cnt++;
        }
    }
    
    // Kruskal
    qsort(edges, edge_cnt, sizeof(Edge), cmp);
    
    for (int i = 1; i <= n; i++)
        parent[i] = i;
    
    int total = 0;
    int cnt = 0;
    for (int i = 0; i < edge_cnt; i++) {
        int u = edges[i].u;
        int v = edges[i].v;
        int w = edges[i].w;
        if (find(u) != find(v)) {
            union_set(u, v);
            total += w;
            cnt++;
            if (cnt == n - 1)
                break;
        }
    }
    
    printf("%d\n", total);
    return 0;
}
相关推荐
m0_518019483 小时前
C++中的委托构造函数
开发语言·c++·算法
m0_743470373 小时前
高性能计算框架实现
开发语言·c++·算法
前端的阶梯3 小时前
深入浅出的聊下AI Agent
算法·架构
Tony沈哲3 小时前
AI 正在进入本地时代,我开源了一个推理平台—— 支持多模型 / Agent / Workflow 的工程实现
人工智能·算法·llm
黎阳之光3 小时前
AI赋能安全新生态 黎阳之光锚定国家政策筑造数智防线
大数据·人工智能·算法·安全·数字孪生
2401_846341653 小时前
调试技巧与核心转储分析
开发语言·c++·算法
D愿你归来仍是少年3 小时前
Apache Flink Checkpoint 与 Chandy-Lamport 算法深度解析
算法·flink·apache
2301_815482934 小时前
C++安全编程指南
开发语言·c++·算法
2401_851272994 小时前
内存映射文件高级用法
开发语言·c++·算法