完全图
题目描述
在图论的数学领域,完全图是一个简单的无向图,其中每对不同的顶点之间都恰连有一条边相连。————百度百科
现在给定一个包含 n 个顶点的完全图,你可以删掉图中的一些边,但是删掉的边不能超过 m 条,请问删去边之后的图最多能有几个连通分量?
输入描述:
第一行包含一个数字 T,表示测试数据组数
接下来 T 行,每行两个正整数n,m,中间用空格隔开
输出描述:
输出 T 行,每行一个整数表示答案
首先要知道无向完全图有 n*(n-1)/2 条边;
然后可以推出规律:
删除边数 | 连通分量数 |
---|---|
n-1 | 1 |
n-1+n-2 | 2 |
n-1+n-2+n-3 | 3 |
… | … |
所以可以二分枚举连通分量数 x ,算出要删除的边数,然后和 m 比较;
但是这题比较变态的是数据范围,可以采用__int128来代替longlong;
代码:
#include<bits/stdc++.h>
#define LL unsigned long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=100100;
const int M=1000100;
const LL mod=100000000;
inline __int128 read(){//输入模板
__int128 x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void print(__int128 x){//输出模板
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
print(x/10);
putchar(x%10+'0');
}
__int128 n,m;
int judge(__int128 p){
__int128 q=p-1;
__int128 s1=n*q-q*(q+1)/2;
__int128 s2=s1+n-p;
if(m<s1) return 0;
if(s1!=s2&&m>=s1&&m<s2) return 1;
else if(s1==s2&&m>=s1) return 1;
return 2;
}
int main(){
__int128 t=read();
while(t--){
n=read(),m=read();
__int128 l=1,r=n;//二分连通分量
__int128 ans=1;
while(l<=r){
__int128 d=(l+r)/2;
int ok=judge(d);
if(ok==0) r=d-1;
else if(ok==2) l=d+1;
else{
ans=d;
break;
}
}
print(ans);
cout<<endl;
}
return 0;
}