BZOJ 1006 [HNOI2008]神奇的國度
阿新 • • 發佈:2017-06-11
html align 大於 防止 continue tdi 沒有 輸出 head
1 2
1 4
2 4
2 3
3 4
Description
K國是一個熱衷三角形的國度,連人的交往也只喜歡三角原則.他們認為三角關系:即AB相互認識,BC相互認識,CA
相互認識,是簡潔高效的.為了鞏固三角關系,K國禁止四邊關系,五邊關系等等的存在.所謂N邊關系,是指N個人 A1A2
...An之間僅存在N對認識關系:(A1A2)(A2A3)...(AnA1),而沒有其它認識關系.比如四邊關系指ABCD四個人 AB,BC,C
D,DA相互認識,而AC,BD不認識.全民比賽時,為了防止做弊,規定任意一對相互認識的人不得在一隊,國王相知道,
最少可以分多少支隊。
Input
第一行兩個整數N,M。1<=N<=10000,1<=M<=1000000.表示有N個人,M對認識關系. 接下來M行每行輸入一對朋
友
Output
輸出一個整數,最少可以分多少隊
Sample Input
4 51 2
1 4
2 4
2 3
3 4
Sample Output
3HINT
一種方案(1,3)(2)(4)
題解
我們把每個人都看做一個點,認識關系看做一條邊,那麽,“最少分多少支隊”就是圖的最小染色數。
我們知道,一般圖的染色數是NPC問題,但是由於題目中的“禁止四邊關系”等,可以發現其沒有長度大於3的無弦環。
那麽,這就是在求弦圖的染色,直接套MCS算法按完美消除序列逆序染色即可。
具體細節請參照 陳丹琦 《弦圖與區間圖》
附代碼:
#include <cctype> #include <cstdlib> #include <cstdio> #include <cstring> const int N = 10050; const int M = 1050000; struct Node{ int v, nxt; }nodes[M]; int cnt; int pre[N], to[M * 2], nxt[M * 2]; int head[N]; int f[N], P[N]; bool vis[N]; int n, m; inline void add(int h, int v) { nodes[++cnt].v = v; nodes[cnt].nxt = head[h]; head[h] = cnt; } void MCS() { memset(nodes, 0, sizeof nodes); memset(head, 0, sizeof head); memset(vis, 0, sizeof vis); memset(f, 0, sizeof f); int i, j, best = 0; for (i = 1; i <= n; ++i) add(0, i); for (j = n; j; --j) while (1) { int x; while (vis[nodes[x = head[best]].v]) head[best] = nodes[x].nxt; if (!x) { --best; continue; } x = nodes[x].v; vis[P[j] = x] = 1; for (i = pre[x]; ~i; i = nxt[i]) { if (vis[to[i]]) continue; add(++f[to[i]], to[i]); if (f[to[i]] > best) best = f[to[i]]; } break; } } int cnt2; inline void addedge(int u, int v) { nxt[cnt2] = pre[u]; to[pre[u] = cnt2++] = v; } inline int readInt() { int ans = 0; char c; do c = getchar(); while (!isdigit(c)); do { ans = ans * 10 + c - ‘0‘; c = getchar(); } while (isdigit(c)); return ans; } int mark[N], color[N]; int main() { cnt = cnt2 = 0; memset(pre, -1, sizeof pre); n = readInt(); m = readInt(); int x, y; while (m--) { x = readInt(); y = readInt(); addedge(x, y); addedge(y, x); } MCS(); memset(color, 0, sizeof color); memset(mark, 0, sizeof mark); int ans = 0; for (int j = n; j; --j) { int x = P[j]; for (int i = pre[x]; ~i; i = nxt[i]) mark[color[to[i]]] = j; for (color[x] = 1; mark[color[x]] == j; ++color[x]); if (color[x] > ans) ans = color[x]; } printf("%d\n", ans); return 0; }
BZOJ 1006 [HNOI2008]神奇的國度