#include using namespace std; const int N = 20010, M = 200010; typedef pair PII; int n, m; int color[N]; // 二分图的标记数组 // 邻接表 int e[M], h[N], idx, w[M], ne[M]; void add(int a, int b, int c) { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; } // bfs实现 int bfs(int u, int limit) { // 假设 1:黑,2:白,这样方便理解一些 color[u] = 1; queue q; // 两个属性:节点号,颜色 q.push({u, 1}); // 将节点u入队列,颜色为黑 while (q.size()) { PII t = q.front(); q.pop(); int u = t.first, c = t.second; // 找到这个节点关联的其它节点 for (int i = h[u]; ~i; i = ne[i]) { if (w[i] <= limit) continue; // 不关心小于limit冲突值的关系 int v = e[i]; // 没染色就染成相反的颜色 if (!color[v]) { color[v] = 3 - c; // 并且把这个新的节点入队列,再探索其它的相邻节点 q.push({v, 3 - c}); } else if (color[v] == c) return 0; // 染过的,有两种情况,一种是与本次要求的染色一样,一种是不一样, // 不一样就是矛盾 } } return 1; } // 使用limit做为最小的冲突值,这样划分的两个图是不是二分图 int check(int limit) { // 清空二分图的标记数组 memset(color, 0, sizeof color); // 这里一般都是枚举每个节点,然后找突破口 for (int i = 1; i <= n; i++) if (color[i] == 0) // 如果没有标记过 // 将i这个点标识为黑色:1 if (!bfs(i, limit)) // 存在冲突,不是二分图,返回false return 0; return 1; // 没有冲突,是二分图 } int main() { scanf("%d %d", &n, &m); memset(h, -1, sizeof h); while (m--) { int a, b, c; scanf("%d %d %d", &a, &b, &c); add(a, b, c), add(b, a, c); } // 二分答案 int l = 0, r = 1e9; while (l < r) { int mid = (l + r) >> 1; if (check(mid)) r = mid; else l = mid + 1; } // 输出最小的匹配值 printf("%d\n", l); return 0; }