• 仙人掌(cactus)


    题目描述
    LYK 在冲刺清华集训(THUSC)!于是它开始研究仙人掌,它想来和你一起分享它最近
    研究的结果。
    如果在一个无向连通图中任意一条边至多属于一个简单环(简单环的定义为每个点至多
    经过一次),且不存在自环,我们称这个图为仙人掌。
    LYK 觉得仙人掌还是太简单了,于是它定义了属于自己的仙人掌。
    定义一张图为美妙的仙人掌,当且仅当这张图是一个仙人掌且对于任意两个不同的点 i,j,
    存在一条从 i 出发到 j 的路径,且经过的点的个数为|j-i|+1 个。
    给定一张 n 个点 m 条边且没有自环的图,LYK 想知道美妙的仙人掌最多有多少条边。
    数据保证整张图至少存在一个美妙的仙人掌。
    输入格式(cactus.in)
    第一行两个数 n,m 表示这张图的点数和边数。
    接下来 m 行,每行两个数 u,v 表示存在一条连接 u,v 的无向边。
    输出格式(cactus.out)
    一个数表示答案
    输入样例
    4 6
    1 2
    1 3
    1 4
    2 3
    2 4
    3 4
    输出样例
    4

    思路:

      题目保证一定存在i到i+1的边。那我就不去处理了。(保证一定存在 1,——2——3——4......n-1——n。这样的链。)

      只要处理  在 1,——2——3——4......n-1——n。这条链上,加上尽可能多的边,不会出现某一个边被包含在多个环中。

      咦!这不就转化成了区间覆盖问题了!

    dp贪心两种写法。

    dp

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    #define MAXN 100010
    int f[MAXN],g[MAXN];
    int n,m;
    int main()
    {
        freopen("cactus.in","r",stdin);
        freopen("cactus.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1,u,v;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            if(u>v)    swap(u,v);
            if(u+1!=v) g[v]=max(g[v],u);
        }
        f[0]=-1;
        for(int i=2;i<=n;i++)
        f[i]=max(f[i-1],f[g[i]]+1);
        printf("%d",f[n]+n-1);
        return 0;
    }

    贪心

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define N 100010
    using namespace std;
    int n,m;
    struct node
    {
        int x,y;
    };node e[N*2];
    bool cmp(const node&s1,const node&s2)
    {
        return s1.y<s2.y;
    }
    int main()
    {
        //freopen("cactus.in","r",stdin);
        //freopen("cactus.out","w",stdout);
        scanf("%d%d",&n,&m);
        int t=0;
        for(int i=1;i<=m;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            if(x>y)swap(x,y);
            if(x+1!=y)e[++t].x=x,e[t].y=y;
        }
        sort(e+1,e+t+1,cmp);
        int tot=0,p=0;
        for(int i=1;i<=t;i++)
          if(e[i].x>=p)p=e[i].y,tot++;
        printf("%d",tot+n-1);
        return 0;
    }
  • 相关阅读:
    n的阶乘
    二叉树遍历
    二分查找练习
    字符串中最长回文序列求解
    复数集合
    AppCrawler自动化遍历使用详解(版本2.1.0 )(转)
    谷歌驱动下载链接
    谷歌浏览器插件
    Pycharm破解方法
    go学习链接
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7635321.html
Copyright © 2020-2023  润新知