AC

许诺  •  16天前


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

const int MAXN = 10005; const int MAXM = 50005; const int INF = 0x3f3f3f3f;

struct Edge {

int u, v, w;
bool operator<(const Edge& other) const {
    return w > other.w; // 按权重降序排序
}

};

vector edges; vector<pair<int, int>> graph[MAXN]; // 最大生成树的邻接表

// 并查集 int parent[MAXN]; int find(int x) {

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

}

bool unite(int x, int y) {

x = find(x);
y = find(y);
if (x == y) return false;
parent[x] = y;
return true;

}

// LCA相关 int depth[MAXN]; int fa[MAXN][15]; // fa[i][j]表示i的2^j级祖先 int minEdge[MAXN][15]; // minEdge[i][j]表示i到2^j级祖先路径上的最小边权

void dfs(int u, int p, int d) {

depth[u] = d;
fa[u][0] = p;

for (int i = 1; (1 << i) <= d; i++) {
    fa[u][i] = fa[fa[u][i-1]][i-1];
    minEdge[u][i] = min(minEdge[u][i-1], minEdge[fa[u][i-1]][i-1]);
}

for (auto& e : graph[u]) {
    int v = e.first, w = e.second;
    if (v != p) {
        minEdge[v][0] = w;
        dfs(v, u, d + 1);
    }
}

}

int query(int x, int y) {

if (find(x) != find(y)) return -1; // 不连通

if (depth[x] < depth[y]) swap(x, y);

int res = INF;
// 将x提到与y同一深度
int diff = depth[x] - depth[y];
for (int i = 0; diff; i++, diff >>= 1) {
    if (diff & 1) {
        res = min(res, minEdge[x][i]);
        x = fa[x][i];
    }
}

if (x == y) return res;

// 同时上跳
for (int i = 14; i >= 0; i--) {
    if (fa[x][i] != fa[y][i]) {
        res = min(res, min(minEdge[x][i], minEdge[y][i]));
        x = fa[x][i];
        y = fa[y][i];
    }
}

res = min(res, min(minEdge[x][0], minEdge[y][0]));
return res;

}

int main() {

int n, m;
cin >> n >> m;

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

// 读入边
for (int i = 0; i < m; i++) {
    int x, y, z;
    cin >> x >> y >> z;
    edges.push_back({x, y, z});
}

// 构建最大生成树
sort(edges.begin(), edges.end());
for (auto& e : edges) {
    if (unite(e.u, e.v)) {
        graph[e.u].push_back({e.v, e.w});
        graph[e.v].push_back({e.u, e.w});
    }
}

// 初始化LCA
memset(minEdge, 0x3f, sizeof(minEdge));
for (int i = 1; i <= n; i++) {
    if (depth[i] == 0) { // 对于每个连通分量
        dfs(i, 0, 1);
    }
}

// 处理查询
int q;
cin >> q;
while (q--) {
    int x, y;
    cin >> x >> y;
    cout << query(x, y) << endl;
}

return 0;

}


评论:

请先登录,才能进行评论