1 条题解

  • 0
    @ 2025-8-24 21:53:24

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Shikita
    **

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

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

    以下是正文


    弦图 完美消除序列

    弦图的前置知识

    诱导子图:子图中任意一条边的两个端点一定也都在这个子图中

    最大团:团中任意两点之间一定都有边,而包含顶点最多的团就是最大团

    最小团覆盖:用最少的团覆盖图中所有的点

    最大独立集:独立集中任意两点之间一定都没有边,而包含顶点最多的独立集就是最大独立集

    最小染色:用最少的颜色给图染色使得图中任意相邻的两点颜色不相同

    弦图:无向图中任意长度大于3的环都至少有一个弦,所谓弦就是连接环中不相邻两点的边

    一般来讲:

    ①最大团数<=最小染色数

    ②最大独立集<=最小团覆盖

    对于弦图来讲:

    ①最大团数==最小染色数

    ②最大独立集==最小团覆盖

    单纯点:如果与顶点V相邻的所有点能构成一个团,那么V就是个单纯点

    ③任何一个弦图都有至少一个单纯点,不是完全图的弦图至少有两个不相邻的单纯点

    完美消除序列:一个点的序列(每个点刚好出现1次)v1,v2,,vnv_1, v_2,…,v_n满足viv_i在诱导子图{vi,vi+1,,vnv_i, v_{i+1},…,v_n}中为一个单纯点

    一个无向图是弦图的充要条件是存在完美消除序列

    再看本题的题意,题目中的数据保证M对矛盾所构成的图中不会有超过3个点的环

    显然符合弦图的定义嘛

    而题目中要求的矛盾关系,就是不能选择相邻的两个点嘛

    妥妥的弦图最大独立集

    做法

    对于这种题目,我们只需要求个完美消除序列就好了,然后在完美消除序列上从前往后贪心取点即可

    对于完美消除序列的求取方法

    从后往前确定序列的点,每取一个点都把还没加入序列的和它相连的点的标号+1,每次取点选择标号最大的点之一,这样我们便可以求出一个完美消除序列

    复杂度 O(m+n)O(m+n)

    接下去在完美消除序列上跑个贪心就好了

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        int x=0;
        char c=getchar();
        bool flag=0;
        while(c<'0'||c>'9') {if(c=='-')flag=1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x+(x<<2)<<1)+ c-'0';c=getchar();}
        return flag?-x:x;
    }
    const int N=1e5+5;
    int n,m,vis[N],seq[N],num[N],id=1,ans;
    int to[N],nxt[N],head[N],cnt;
    vector<int>cg[N];
    void add(int u,int cg){to[++cnt]=cg;nxt[cnt]=head[u];head[u]=cnt;}
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=m;++i)
        {
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        for(int i=1;i<=n;++i) cg[0].push_back(i);
        for(int i=1;i<=n;++i)
        {
            int fg=0,now;
            while(!fg)
            {
                for(int j=cg[id].size()-1;j>=0;--j)
                if (!vis[cg[id][j]]) {fg=1;now=cg[id][j];break;}
                else cg[id].pop_back();
                if(!fg) --id;
            }
            seq[i]=now;vis[now]=1;
            for (int e=head[now];e;e=nxt[e])
            if (!vis[to[e]])
            {
                cg[++num[to[e]]].push_back(to[e]);
                id=max(id,num[to[e]]);
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=n;i;--i) if(!vis[seq[i]])
        {
            ++ans;vis[seq[i]]=1;
            for(int e=head[seq[i]];e;e=nxt[e]) vis[to[e]]=1;
        }
        printf("%d\n",ans);
    }
    
    • 1

    信息

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