rt,思路是二分,上界是每个点连向的权值最小的两条边的和的最小值,然后 check(mid) 的时候只保留权值小于 mid 的边,判断能否成为二分图。只过了六个点。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, flag, l, r, ans=1e18, f[400010];
struct edge{
int x, y, z;
}a[200010];
multiset <int> s[200010];
multiset <int> :: iterator it, itt;
int find(int x){
if (x != f[x]) return f[x] = find(f[x]);
return f[x];
}
int check(int x){
for (int i=1; i<=n+n; i++) f[i] = i;
int pd = 1;
for (int i=1; i<=m; i++){
if (a[i].z < x){
int fx = find(a[i].x), fy = find(a[i].y+n);
if (fx != fy) f[fy] = fx;
fx = find(a[i].x+n), fy = find(a[i].y);
if (fx != fy) f[fy] = fx;
}
}
for (int i=1; i<=n; i++){
if (find(i) == find(i+n)) pd = 0;
}
return pd;
}
signed main(){
scanf ("%lld%lld", &n, &m);
for (int i=1; i<=m; i++){
scanf ("%lld%lld%lld", &a[i].x, &a[i].y, &a[i].z);
s[a[i].x].insert(a[i].z); s[a[i].y].insert(a[i].z);
}
for (int i=1; i<=n; i++){
int now = 0;
if (s[i].size() >= 2){
it = s[i].begin();
now += *it;
itt = s[i].begin(); itt ++;
now += *itt;
}
ans = min(ans, now);
}
l = 0, r = ans;
while (l <= r){
int mid = l + r >> 1;
if (check(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
printf ("%lld\n", ans);
return 0;
}