• BZOJ 1006 [HNOI2008]神奇的国度


    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
    ", ans);
      return 0;
    }
    

      

  • 相关阅读:
    API接口安全设计方案(已实现)
    第8篇-dispatch_next()函数分派字节码
    第7篇-为Java方法创建栈帧
    第6篇-Java方法新栈帧的创建
    第5篇-调用Java方法后弹出栈帧及处理返回结果
    第4篇-JVM终于开始调用Java主类的main()方法啦
    第3篇-CallStub新栈帧的创建
    第2篇-JVM虚拟机这样来调用Java主类的main()方法
    第1篇-关于JVM运行时,开篇说的简单些
    SpringCloud和SpringCloudAlibaba超详细总结
  • 原文地址:https://www.cnblogs.com/y-clever/p/6984162.html
Copyright © 2020-2023  润新知