zoukankan      html  css  js  c++  java
  • 简单题

    【问题描述】

    dzy 手上有一张 n 个点 m 条边的联通无向图。仙人掌是一张每条边最多在一个简单环内的联通无向图。他想求这个无向图的生成仙人掌中最多有多少条边。生成仙人掌是原图的生成子图,生成子图包括原图的全部点与部分边。但是 dzy 觉得这个问题太简单了,于是他定义了“美丽的生成仙人掌”,即在一个生成仙人掌中如果满足对于任意编号为 i,j(i < j) 的两点,存在一条它们之间的简单路径上面有 j-i+1 个点,则这个仙人掌是美丽的。他现在想要知道这张图的美丽的生成仙人掌中最多有多少条边,你能帮帮他
    吗?

    【输入】

    第一行两个整数 n,m。接下来 m 行每行两个整数 ui,vi,表示这两个点之
    间有一条无向边。保证图中没有自环。

    【输出】

    仅一行一个整数表示答案。

    【输入输出样例 】

    simple.in
    2 1
    1 2

    simple.out
    1

    【数据规模和约定】

    对于 10% 的数据,n <=10。
    对于 30% 的数据,n <=10^3。
    对于 100% 的数据,n <=10^5 ;m <= 2n。

    【题解】

    这里写图片描述

    考试时我没看懂题目,一眼以为是图论题,却又无从下手。(听说有的命题人喜欢把难题命名为“大水题”?)

    结果还真是道贪心大水题!!!

    根据题意,因为数据保证有解,所以在图中必定存在一条从1 -> 2 -> … -> n的链,最后的答案呢肯定是以此为基础的。

    我们把 1 到 n 的这条链看作是一条线段。再加边看作是用一条新的线段来覆盖。根据仙人掌图的定义,任何一条边不能同时存在于两个不同的环中。意思就是在新加的这些线段中不能有任何两条线段覆盖同一个区域。求最多的边就是求最多的线段。这不就是一个简单的线段覆盖问题么? 把所有边按右端点排序,一个贪心就好了。

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define fp(i,a,b) for(int i=a;i<=b;i++)
    #define fq(i,a,b) for(int i=a;i>=b;i--)
    #define il inline
    #define ll long long 
    using namespace std;
    const int maxn=1e5+5;
    struct Edge
    {
        int l,r;
    }a[maxn<<1];
    int n,m,vis[maxn]={};
    il bool cmp(Edge x,Edge y)
    {
        return x.r<y.r;
    }
    il int gi()
    {
       int x=0;
       short int t=1;
       char ch=getchar();
      while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    int main()
    {
        freopen("simple.in","r",stdin);
        freopen("simple.out","w",stdout);
        n=gi();m=gi();
        fp(i,1,m)
        {
            int x=gi(),y=gi();
            if(x>y) swap(x,y);
            a[i]=(Edge){x,y};
        }
        sort(a+1,a+1+m,cmp);
        int x=1,ans=n-1;
        fp(i,1,m)
        {
            if(a[i].r==a[i].l+1&&!vis[a[i].l]) {vis[a[i].l]=1;continue;}
            if(a[i].l<x) continue;
            x=a[i].r;
            ans++;
        }
        printf("%d
    ",ans);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    数组对象遍历新增属性
    watch监听数据的改变
    同一个数组查重
    SpringCloud搭建(二) 支付模块搭建
    SpringCloud搭建(一) 聚合父工程搭建
    线程池
    同步容器
    容器
    JVM学习
    线程---ThreadLocal
  • 原文地址:https://www.cnblogs.com/yanshannan/p/7413148.html
Copyright © 2011-2022 走看看