[BZOJ1006][HNOI2008][弦图的最小点染色]神奇的国度

来源:互联网 发布:sqlserver rowguid 编辑:程序博客网 时间:2024/05/19 18:41

题意


N个人M条关系,两两认识的人不能分在一组,询问最少能分多少组


最小点染色模板题,CDQ《弦图与区间图》例题
用mcs求出完美消除序列,从后往前染色就行了

具体看CDQ的论文

#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <algorithm>#define N 20010#define M 2000010using namespace std;int n,m,u,v,cnt,Ans;int G[N],vis[N],p[N],c[N],t[N];struct edge{  int t,nx;}E[M<<1];struct stp{  stp *l,*r;  int g;}A[N],*B[N];inline void reaD(int &x){  char c=getchar();x=0;  for(;c>57||c<48;c=getchar());for(;c>=48&&c<=57;x=x*10+c-48,c=getchar());}inline void Insert(int x,int y){  E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;  E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt;}int main(){  reaD(n); reaD(m);  for(int i=1;i<=m;i++)    reaD(u),reaD(v),Insert(u,v);  for(int i=1;i<=n;i++){    if(i>1) A[i].l=&A[i-1];    if(i<n) A[i].r=&A[i+1];    A[i].g=i;  }  B[0]=&A[1]; int maxx=0;  for(int i=n;i;i--){    while(!B[maxx]) maxx--;    int x=B[maxx]->g;    if(B[maxx]->r) B[maxx]->r->l=0;    B[maxx]=B[maxx]->r;    p[i]=x; vis[x]=1;    for(int j=G[x];j;j=E[j].nx){      int v=E[j].t;      if(vis[v]) continue;      if(A[v].l) A[v].l->r=A[v].r;      else B[c[v]]=A[v].r;      if(A[v].r) A[v].r->l=A[v].l;      c[v]++; A[v].l=0;      if(B[c[v]])B[c[v]]->l=&A[v];      A[v].r=B[c[v]];      B[c[v]]=&A[v];      if(c[v]>maxx) maxx=c[v];    }  }  memset(vis,0,sizeof(vis));  memset(c,0,sizeof(c));  for(int i=n;i;i--){    int v=p[i];    vis[v]=1;    for(int j=G[v];j;j=E[j].nx)      if(vis[E[j].t]) t[c[E[j].t]]=i;    int k=1;    while(t[k]==i) k++;    Ans=max(Ans,k);    c[v]=k;  }  printf("%d\n",Ans);  return 0;}
0 0