1. 程式人生 > >BZOJ 1006 [HNOI2008]神奇的國度

BZOJ 1006 [HNOI2008]神奇的國度

html align 大於 防止 continue tdi 沒有 輸出 head

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 5
1 2
1 4
2 4
2 3
3 4

Sample Output

3

HINT

  一種方案(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]神奇的國度