题目描述
给定一个 个点, 条边的无向图,每条边有一个权值。
问是否存在一条从 1 到 的路径使得路径上的权值的最大值最小,求出这个最大值。
如果 1 号点和 号点不连通,则输出 -1。
注意:请勿采用递归形式的DFS,谨防爆栈。
输入格式
第一行两个整数 ,。
接下来 行,每行三个整数 表示在 和 之间存在一条权值为 的无向边。
输出格式
一个整数表示答案。
样例输入1
4 5
1 2 2
2 3 3
2 3 2
3 4 1
1 4 5
样例输出1
2
样例输入2
3 2
1 2 1
1 2 5
样例输出2
-1
思路
首先,定义一个并查集的数据结构,其中pre[N]表示每个节点的父节点,sz[N]表示以每个节点为根的子树的大小。init函数用于初始化并查集,root函数用于查找一个节点的根节点,merge函数用于合并两个节点所在的集合,check函数用于检查两个节点是否在同一个集合中。
在主函数中,首先读取节点和边的数量,然后初始化并查集。接着,读取每条边的信息,并将其添加到edge向量中。然后,使用sort函数将edge向量中的边按照权值从小到大排序。
接下来,遍历排序后的边,尝试合并每条边的两个端点。如果1号点和n号点在同一个集合中,那么就找到了一条从1号点到n号点的路径,路径上的权值的最大值最小,然后输出这个最大值。
如果遍历完所有的边后,1号点和n号点还不在同一个集合中,那么就输出-1,表示1号点和n号点不连通。
AC代码
#include <algorithm>
#include <iostream>
#include <vector>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;
const int N = 1e6 + 7;
struct Sedge {
int u, v, w;
};
int n, m;
int pre[N], sz[N];
vector<Sedge> edge;
void init(int n) {
for (int i = 1; i <= n; i++) {
pre[i] = i;
sz[i] = 1;
}
}
int root(int x) {
int i = x;
while (pre[i] != i) {
i = pre[i];
}
return i;
}
void merge(int x, int y) {
int rx = root(x);
int ry = root(y);
if (rx == ry) {
return;
}
// cout << x << " " << y << endl;
if (sz[rx] > sz[ry]) {
swap(rx, ry);
}
pre[rx] = ry;
sz[ry] += sz[rx];
}
bool check(int x, int y) {
int rx = root(x);
int ry = root(y);
return rx == ry;
}
bool cmp(Sedge x, Sedge y) { return x.w < y.w; }
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
init(n);
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
edge.push_back({u, v, w});
}
sort(edge.begin(), edge.end(), cmp);
auto it1 = edge.begin();
for (; it1 != edge.end(); it1++) {
merge(it1->u, it1->v);
if (check(1, n)) {
break;
}
}
// 检查是否联通
cout << (check(1, n) ? it1->w : -1) << endl;
return 0;
}