求调 ARC C
  • 板块学术版
  • 楼主苏联小渣
  • 当前回复4
  • 已保存回复4
  • 发布时间2023/9/18 09:09
  • 上次更新2023/11/2 19:21:52
查看原帖
求调 ARC C
399286
苏联小渣楼主2023/9/18 09:09

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;
}
2023/9/18 09:09
加载中...