Acwing 257. 关押罪犯 (染色法判二分图)
把囚犯分成两部分,显然是一个二分图
- 二分答案,使问题状态化简为1和0,考虑如何check
- 贪心:如果两个囚犯之间怨气值小于等于mid,则不用管他们,否则把他们分成两拨(染异色)
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<ll, ll>
const int N = 2e4 + 5;
const int M = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double PI = acos(-1.0);
int h[N], e[M], w[M], ne[M], idx;
int n, m;
int col[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
bool dfs( int u, int c, ll val ) {
col[u] = c;
for ( int i = h[u]; ~i; i = ne[i] ) {
int v = e[i];
if(w[i] <= val) continue;
if(col[v]){ if(col[v] == c) return false;}
else if(!dfs(v, 3 - c, val)) return false;
}
return true;
}
bool check(int limit)
{
memset(col, 0, sizeof col);
for (int i = 1; i <= n; i ++ )
if (col[i] == 0)
if (!dfs(i, 1, limit))
return false;
return true;
}
int main () {
IOS
memset(h, -1, sizeof h);
cin >> n >> m;
for ( int i = 1; i <= m; ++ i ) {
int u, v, c; cin >> u >> v >> c; ++ u, ++ v;
add(u, v, c); add(v, u, c);
}
ll l = 0, r = 1000000000;
while(l < r) {
ll mid = l + r >> 1;
if( check(mid) ) r = mid;
else l = mid + 1;
}
cout << l << '\n';
return 0;
}