给定一个 n n n 个点, m m m 条边的无向图,每条边有一个权值。
问是否存在一条从 1 到 n n n 的路径使得路径上的权值的最大值最小,求出这个最大值。
如果 1 号点和 n n n 号点不连通,则输出 -1。
注意:请勿采用递归形式的DFS,谨防爆栈。
第一行两个整数 n n n, m m m。 ( 2 ≤ n ≤ 2 × 1 0 5 , 1 ≤ m ≤ 2 × 1 0 5 ) (2 \leq n \leq 2 \times 10^5, 1 \leq m \leq 2 \times 10^5) (2≤n≤2×105,1≤m≤2×105)
接下来 m m m 行,每行三个整数 u i , v i , w i u_i,v_i,w_i ui,vi,wi 表示在 u i u_i ui 和 v i v_i vi 之间存在一条权值为 w i w_i wi 的无向边。 ( 1 ≤ u i , v i ≤ n , 0 ≤ w i ≤ 1 0 4 ) (1 \leq u_i, v_i \leq n, 0 \leq w_i \leq 10^4) (1≤ui,vi≤n,0≤wi≤104)
一个整数表示答案。
4 5
1 2 2
2 3 3
2 3 2
3 4 1
1 4 5
2
3 2
1 2 1
1 2 5
-1
首先,定义一个并查集的数据结构,其中pre[N]
表示每个节点的父节点,sz[N]
表示以每个节点为根的子树的大小。init
函数用于初始化并查集,root
函数用于查找一个节点的根节点,merge
函数用于合并两个节点所在的集合,check
函数用于检查两个节点是否在同一个集合中。
在主函数中,首先读取节点和边的数量,然后初始化并查集。接着,读取每条边的信息,并将其添加到edge
向量中。然后,使用sort
函数将edge
向量中的边按照权值从小到大排序。
接下来,遍历排序后的边,尝试合并每条边的两个端点。如果1号点和n号点在同一个集合中,那么就找到了一条从1号点到n号点的路径,路径上的权值的最大值最小,然后输出这个最大值。
如果遍历完所有的边后,1号点和n号点还不在同一个集合中,那么就输出-1,表示1号点和n号点不连通。
#include
#include
#include
#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;
}