Vasya and Isolated Vertices

题目大意是,输入n,m两个数,n代表有n个点,m代表可以连m条边,但是不可以连同一条边,而且边是无向边,求被孤立的也就是没有边连的点的最小数和最大数

题目描述

Vasya has got an undirected graph consisting of n vertices and m edges. This graph doesn't contain any self-loops or multiple edges. Self-loop is an edge connecting a vertex to itself. Multiple edges are a pair of edges such that they connect the same pair of vertices. Since the graph is undirected, the pair of edges (1,2) and (2,1) is considered to be multiple edges. Isolated vertex of the graph is a vertex such that there is no edge connecting this vertex to any other vertex.

Vasya wants to know the minimum and maximum possible number of isolated vertices in an undirected graph consisting of n vertices and m edges.

输入描述

The only line contains two integers n and m (1≤n≤105,0≤m≤2n(n−1)​).

It is guaranteed that there exists a graph without any self-loops or multiple edges with such number of vertices and edges.

输出描述

In the only line print two numbers min and max — the minimum and maximum number of isolated vertices, respectively.

样例输入 1 

4 2

样例输出 1 

0 1

样例输入 2 

3 1

样例输出 2 

1 1

说明

In the first example it is possible to construct a graph with 0 isolated vertices: for example, it should contain edges (1,2) and (3,4). To get one isolated vertex, we may construct a graph with edges (1,2) and (1,3).

In the second example the graph will always contain exactly one isolated vertex.

拿到这道题第一反应,最小数简单呀,让边充分利用点呗,一边占两条边,所以small=n-2*m;

但要注意的是small可能为负值,所以要判断一下如果为负值,就令small=0;

但最大值有点麻烦,一开始想错了,也就实现错了,没有想到内部也是可以连线的,也就是对角线,所以边想少了,其实也不用太去想的复杂了,一个公式就可以解决,就是当你用for循环遍历的时候,结果TLE了,那么你就要更改思路了,不要听题目说什么你就写什么,要搞懂题目的意思,巧妙地转化题目条件,本题条件就是然后我们来实现一下,如果for循环超时,可以用二分法优化一下

#include<iostream>

#include<cstdio>
#define ll long long
using namespace std;
ll n,m;
ll calc(){
    for(ll i=1;i<=m;i++){
        if(i*(i+1)/2>=m)return n-i-1;
    }
}
int main(){
    scanf("%lld%lld",&n,&m);
    ll sma=n-2*m;
    if(n<=2*m)sma=0;
    ll big=calc();
    if(m==0){
        sma=n;
        big=n;
    }
    printf("%lld %lld",sma,big);
    return 0;
}

二分法优化后的

#include<iostream>
#include<algorithm>
using namespace std;
template <typename T>
inline void read(T &x){
    x=0;char ch=getchar();bool f=false;
    while(!isdigit(ch)) f|=ch=='-',ch=getchar();
    while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=f?-x:x;return;
}
template <typename T>
inline void print(T x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10^48);return;
}
#define ll long long
ll n,m;
int main(){
    read(n),read(m);ll minn=0,maxn=0;
    minn=max(0ll,n-2*m);print(minn),putchar(' ');
    ll l=0,r=n;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(mid*(mid-1)/2>=m)    r=mid-1,maxn=mid;
        else l=mid+1;
    }
    print(n-maxn);
    return 0;
}

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值