BZOJ 1006 【HNOI2008】 神奇的国度

题目链接:神奇的国度

  一篇论文题……神奇的弦图,神奇的MCS……

  感觉我没有什么需要多说的,这里简单介绍一下MCS:

  我们给每个点记录一个权值,从后往前依次确定完美消除序列中的点,每次选择权值最大的一个点(相同的话随意选一个)放到当前完美消除序列中的位置,然后把相邻的所有点权值加\(1\)。一路到底即可得到一种完美消除序列。使用链表可以将复杂度优化到\(O(n+m)\)。在弦图中有 最小染色=团数,求完美消除序列的时候顺便统计即可。

  好吧,上面实在扯淡。其实还是要看\(CDQ\)当年的\(ppt\)才好懂……给个链接:弦图与区间图

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 10010
#define maxm 1000010
 
using namespace std;
typedef long long llg;
 
int n,nn,m,a[maxn],best,b[maxn],ans;
int head[maxn],next[maxm<<1],to[maxm<<1],tt;//原图邻接表
int he[maxn],ne[maxm],zh[maxm];//挂链存储
bool vis[maxn];
 
int getint(){
    int w=0;bool q=0;
    char c=getchar();
    while((c>'9'||c<'0')&&c!='-') c=getchar();
    if(c=='-') c=getchar(),q=1;
    while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    return q?-w:w;
}
 
void link(int x,int y){
    to[++tt]=y;next[tt]=head[x];head[x]=tt;
    to[++tt]=x;next[tt]=head[y];head[y]=tt;
}
 
int main(){
    File("a");
    n=nn=getint(); m=getint();
    while(m--) link(getint(),getint()); tt=0;
    for(int i=1;i<=n;i++) zh[++tt]=i,ne[tt]=he[0],he[0]=tt;
    while(best>=0){
        ans=max(ans,best);//统计最大团数
        while(he[best]){
            int u=zh[he[best]],be=0; he[best]=ne[he[best]];
            if(!vis[u]) a[nn--]=u,vis[u]=1;
            else continue;
            for(int i=head[u],v;v=to[i],i;i=next[i])
                if(!vis[v]){
                    b[v]++; zh[++tt]=v;//相邻点权值加1并新建一个节点
                    ne[tt]=he[b[v]]; he[b[v]]=tt;
                    if(b[v]>best) best=b[v],be=1;
                }
            if(be){best++; break;}
        }
        best--;
    }
    printf("%d",ans+1);
    return 0;
}
posted @ 2017-01-07 17:30  lcf2000  阅读(335)  评论(0编辑  收藏  举报