1 条题解

  • 0
    @ 2025-8-24 21:46:22

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar kczno1
    **

    搬运于2025-08-24 21:46:22,当前版本为作者最后更新于2017-03-17 22:45:36,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    求弦图点色数。

    考虑按完美消除序列从后往前,每个点贪心选择最小可染颜色,

    那么他会产生的颜色种类<=所在团大小,

    而一个团由于两两连边,每个点颜色都不同,所以产生的颜色种类>=团的大小,

    所以弦图点色数就是弦图最大团的大小。

    得到完美消除序列用最大势算法,每次选择与最多已选择点相连的点,

    由于每次势最多+1,可以对每个值开个双向链表存势为该值的点,可以做到O(1)删除插入,

    这样时间就是线性。

    之后判断弦图就从后往前扫,检验x与相连的后面的点N(x)是否构成一个团,

    就是先找到N(x)里最小的,之后检验他与N(x)其他点是否相连( 用hash表,bitset(压空间)存都是O(1)的 ),

    如果不相连显然就不是团,如果相连,由于在他检验的时候已经保证N(x)是个团,那么加入一个和所有点都有连边的点显然还是一个团。

    这样每条边只被枚举一次,也是线性的。

    (当然这题不需要判断)

    #include<cstdio> 
    
    #define N 10010
    #define M 1000100
    int n,m,i,x,y,k;
    int t[N];
    struct edge
    {
        int to,next;
    }l[M<<1];int e;
    void add_e(int x,int y)
    {
        l[++e]=(edge){y,t[x]};t[x]=e;
    }
    
    int next[N<<1],pre[N<<1];
    int w[N],q[N],dy[N];
    
    void push(int x)
    {
        pre[next[x]=next[N+w[x]]]=x;
        next[pre[x]=N+w[x]]=x;
    }
    void del(int x)
    {
        pre[next[x]]=pre[x];next[pre[x]]=next[x];
    }
    
    int main()
    {
        freopen("1.in","r",stdin);
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;++i)
        {
            scanf("%d%d",&x,&y);
            add_e(x,y);add_e(y,x); 
        }
        for(i=1;i<=n;++i) push(i);
        int now=0,ans=0;
        for(k=n;k;--k,++now)
        {
            while(!next[N+now])--now;
            x=next[N+now];
            del(x);
            q[k]=x;dy[x]=k;
            int sum=1;
            for(i=t[x];y=l[i].to;i=l[i].next)
            if(!dy[y]) 
            {
                del(y);
                ++w[y];
                push(y);
            }
            else ++sum;
            if(sum>ans)ans=sum;
        }
        printf("%d\n",ans);
    }
    
    • 1

    信息

    ID
    2269
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者