题目链接
并查集+贪心当然是可以做的。
但我用二分图+二分答案。
二分一个\(mid\),删去所有边权小于等于\(mid\)的边,看有没有奇环存在,如果存在,则\(mid\)不行。
#include <cstdio>
#include <algorithm>
using namespace std;
#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define Close fclose(stdin);fclose(stdout);
inline int read(){
int s = 0;
char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s;
}
const int MAXN = 20010;
const int MAXM = 100010;
struct Edge{
int next, to, dis;
}e[MAXM << 1];
int head[MAXN], num, color[MAXN], n, m, l, r, a, b, c;
inline void Add(int from, int to, int dis){
e[++num] = (Edge){ head[from], to, dis }; head[from] = num;
e[++num] = (Edge){ head[to], from, dis }; head[to] = num;
}
int Match(int u, int Color, int p){
color[u] = Color;
for(int i = head[u]; i; i = e[i].next)
if(e[i].dis > p){
if(!color[e[i].to])
if(!Match(e[i].to, 3 - Color, p))
return 0;
else;
else if(color[e[i].to] == Color)
return 0;
}
return 1;
}
int Judge(int p){
memset(color, 0, sizeof color);
for(int i = 1; i <= n; ++i)
if(!color[i])
if(!Match(i, 1, p))
return 0;
return 1;
}
int main(){
Open("*");
n = read(); m = read();
for(int i = 1; i <= m; ++i){
a = read(); b = read(); c = read();
Add(a, b, c); r = max(r, c);
}
while(l < r){
int mid = (l + r) >> 1;
if(Judge(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
return 0;
}