zoukankan      html  css  js  c++  java
  • [10.27_P3] 简单题 (脑洞)


    Description

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

    Input

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

    Output

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

    Sample Input

    2 1
    1 2

    Sample Output

    1

    Hint

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

    时间限制:1S

    空间限制:256M


    题解

    这是道好题。最开始拿到题,第一反应这是道图论题。但是想了很久都想不出来该怎么搞。
    根据题意,因为数据保证有解,所以在图中必定存在一条从1 -> 2 -> ... -> n的链,最后的答案呢肯定是以此为基础的。
    我们把 1 到 n 的这条链看作是一条线段。再加边看作是用一条新的线段来覆盖。根据仙人掌图的定义,任何一条边不能同时存在于两个不同的环中。意思就是在新加的这些线段中不能有任何两条线段覆盖同一个区域。求最多的边就是求最多的线段。这不就是一个简单的线段覆盖问题么? 把所有边按右端点排序,一个贪心就好了。

    代码

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 1e5 + 5;
    int n,m;
    int vis[maxn];
    
    struct edge {
    	int l,r;
    	bool operator < (const edge &a) const {
    		return r < a.r;
    	}
    }e[maxn << 1];
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for(int i = 0;i < m;i++) {
    		int x,y;scanf("%d%d",&x,&y);if(x > y)swap(x,y);
    		e[i] = (edge){x,y};
    	}
    	sort(e,e+m);
    	int x = 1;
    	int ans = n - 1;
    	for(int i = 0;i < m;i++) {
    		if(e[i].r == e[i].l+1&&!vis[e[i].l]) {vis[e[i].l] = 1;continue;}
    		if(e[i].l < x)continue;
    		x = e[i].r;ans++;
    	}
    	
    	printf("%d",ans);
    	return 0;
    } 
    
  • 相关阅读:
    docker底层原理
    搭建docker私有镜像仓库harbor
    docker 网络详解
    从对集合数据去重到Distinct源码分析
    学习笔记(3)centos7 下安装RabbitMQ
    学习笔记(2)centos7 下安装mysql
    学习笔记(1)centos7 下安装nginx
    2.Redis的数据类型
    1.Redis介绍以及安装
    mongoDB的安装和配置
  • 原文地址:https://www.cnblogs.com/ZegWe/p/6013247.html
Copyright © 2011-2022 走看看