You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

AcWing 1142. 繁忙的都市

一、题目描述

城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造。

城市C的道路是这样分布的:

城市中有 n 个交叉路口,编号是 1n,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连接。

这些道路是 双向 的,且把所有的交叉路口直接或间接的连接起来了。

每条道路都有一个分值,分值越小 表示这个道路 越繁忙,越需要进行改造。

但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求:

1改造的那些道路能够把所有的交叉路口直接或间接的连通起来。

2在满足要求1的情况下,改造的道路尽量少。

3在满足要求1、2的情况下,改造的那些道路中分值 最大值尽量小

作为市规划局的你,应当作出最佳的决策,选择哪些道路应当被修建。

输入格式 第一行有两个整数 n,m 表示城市有 n 个交叉路口,m 条道路。

接下来 m 行是对每条道路的描述,每行包含三个整数u,v,c 表示交叉路口 uv 之间有道路相连,分值为 c

输出格式 两个整数 s,max,表示你选出了几条道路,分值最大的那条道路的分值是多少。

二、Kruskal算法

#include <bits/stdc++.h>
using namespace std;

const int N = 310, M = 8010;
// 记录边的结构体
struct Edge {
    int a, b, w;
    const bool operator<(const Edge &t) const {
        return w < t.w;
    }
} e[M];

int n, m;
int p[N];

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

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) p[i] = i; // 并查集初始化

    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        e[i] = {a, b, c};
    }
    // 排序(按边权)
    sort(e, e + m);

    int res = 0;
    for (int i = 0; i < m; i++) {
        int a = find(e[i].a), b = find(e[i].b), w = e[i].w;
        if (a != b) {
            p[a] = b;
            res = w; // 越往后越大
        }
    }
    printf("%d %d\n", n - 1, res);
    return 0;
}

三、Prim算法

#include <bits/stdc++.h>
using namespace std;

const int N = 310;
int dist[N];
int g[N][N];
int n, m;
bool st[N];

int prim() {
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    int res = 0;
    for (int i = 0; i < n; i++) {
        int t = -1;
        for (int j = 1; j <= n; j++)
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        st[t] = true;
        res = max(res, dist[t]); // 找出最长,不要累加和
        for (int j = 1; j <= n; j++)
            dist[j] = min(dist[j], g[t][j]);
    }
    return res;
}

int main() {
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);

    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    printf("%d %d\n", n - 1, prim());
    return 0;
}