#include using namespace std; const int N = 20010, M = 200010; 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++; } // 是不是一个合法的二分图 // u:节点号 c:颜色,1:黑,2:白 3-c:互转, limit:最小冲突值 int dfs(int u, int c, int limit) { color[u] = c; // 染色为c for (int i = h[u]; ~i; i = ne[i]) { // 枚举每条出边 if (w[i] <= limit) continue; // 不关心小于limit冲突值的关系 // 如果没有被continue掉,说明这条边i的冲突w[i]是大于两个监狱之间的最大冲突的,需要把这两个人放到不同的监狱里 int v = e[i]; if (color[v]) { // 如果v染过色 if (color[v] == c) return 0; // 并且与u一样,那就冲突了 } else if (!dfs(v, 3 - c, limit)) // 如果没有染过色,并且在后续的染色过程中出现冲突,也就是无法成为合法二分图 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 (!dfs(i, 1, 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; }