Acwing 257. 关押罪犯 (染色法判二分图)

image
把囚犯分成两部分,显然是一个二分图

  • 二分答案,使问题状态化简为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;
}
posted @ 2022-04-05 09:39  qingyanng  阅读(27)  评论(0编辑  收藏  举报