257. 关押罪犯
題意:
S城現有兩座監獄,一共關押著N名罪犯,編號分別為1~N。他們之間的關系自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發沖突。我們用“怨氣值”(一個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c的罪犯被關押在同一監獄,他們倆之間會發生摩擦,并造成影響力為c的沖突事件。
每年年末,警察局會將本年內監獄中的所有沖突事件按影響力從大到小排成一個列表,然后上報到S城Z市長那里。公務繁忙的Z市長只會去看列表中的第一個事件的影響力,如果影響很壞,他就會考慮撤換警察局長。
在詳細考察了N名罪犯間的矛盾關系后,警察局長覺得壓力巨大。他準備將罪犯們在兩座監獄內重新分配,以求產生的沖突事件影響力都較小,從而保住自己的烏紗帽。假設只要處于同一監獄內的某兩個罪犯間有仇恨,那么他們一定會在每年的某個時候發生摩擦。那么,應如何分配罪犯,才能使Z市長看到的那個沖突事件的影響力最小?這個最小值是多少?
題解:
二分+染色法判斷二分圖
題目要求我們找到將點分為兩組,使得各組內邊的權值的最大值盡可能小
我們就二分一個limit,當limit固定后,因為我們要將所有點分為兩組,這樣邊就存在兩組情況,一種是在組內,一種是在組間,我們的答案是要記錄組內的,所有我們要讓大于limit的邊都在組間,那么剩下在組內的邊都是小于limit的。
我們用染色法判斷大于limit的邊(也就說組間的邊)能否構成二分圖
染色法判二分圖復雜度是O(n+m)
二分是logC
總的復雜度O((N+M)logC)
代碼:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N = 20010, M = 200010;int n, m; int h[N], e[M], w[M], ne[M], idx; int color[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, int limit) {color[u] = c;for (int i = h[u]; ~i; i = ne[i]){if (w[i] <= limit) continue;int j = e[i];if (color[j]){if (color[j] == c) return false;}else if (dfs(j, 3 - c, limit)==0) return false;}return true; }bool check(int limit) {memset(color, 0, sizeof color);for (int i = 1; i <= n; i ++ )if (color[i] == 0)if (!dfs(i, 1, limit))return false;return true; }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; }總結
- 上一篇: 如何加入微服务 Apache Servi
- 下一篇: 503. 借教室