题目链接:##
题目分析:##
由最后划分的结果在两个集合,联想到二分图
又由于答案具有单调性,即如果当前答案可以则更大的答案也一定可以,想到二分答案
思路:
二分答案,每次对于答案进行检验,检验时将(<=)答案的边都忽略掉,只保留比答案大的边,然后进行染色判定二分图,如果能构成二分图,说明这些点可以被分在两个不同的集合,且由二分图的定义可以得到,集合内的点之间无连边,而两集合之间的连边在本题的背景下等于被断掉了,即可以保证有分配方案使得冲突值小于二分到的答案
代码:##
#include<bits/stdc++.h>
#define N 50010
#define M 200010
using namespace std;
inline int read() {
int cnt = 0, f = 1; char c;
c = getchar();
while (!isdigit(c)) {
if (c == '-') f = -f;
c = getchar();
}
while (isdigit(c)) {
cnt = cnt * 10 + c - '0';
c = getchar();
}
return cnt * f;
}
int first[N], nxt[M], to[M], w[M], tot, Max = -1, ans;
int color[N];
int n, m, x, y, z;
void add(int x, int y, int z) {
nxt[++tot] = first[x];
first[x] = tot;
to[tot] = y;
w[tot] = z;
}
bool Dfs (int u, int t) {
for (register int i = first[u]; i; i = nxt[i]) {
if (w[i] <= t) continue;
int v = to[i];
if (!color[v]) {
color[v] = 3 - color[u];
if(!Dfs(v, t)) return false;
}
else if (color[v] == color[u]) return false;
}
return true;
}
bool check (int res) {
memset(color, 0, sizeof(color));
bool flag = true;
for (register int i = 1; i <= n; i++) {
if (!color[i]) {
color[i] = 1;
if(!Dfs(i, res)) {
flag = false;
break;
}
}
}
return flag;
}
int solve(int r) {
int l = 0;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
int main() {
n = read(); m = read();
for (register int i = 1; i <= m; i++) {
x = read(); y = read(); z = read();
add(x, y, z);
add(y, x, z);
if (z > Max) Max = z;
}
ans = solve(Max);
printf("%d", ans);
return 0;
}