题意
不想说,其实题意蛮简单的
题解
n
n
n个点,
m
m
m条边
1、首先
n
n
n个离散点,必然有
4
n
4n
4n条边
2、设
k
k
k为黑点之间的边,
4
n
−
2
k
=
m
4n-2k=m
4n−2k=m,所以
m
m
m是偶数
3、我们可以发现,如果形成一个矩形,并且点在中间的时候最优,这个时候边数是
m
=
2
(
r
+
w
)
m=2(r+w)
m=2(r+w),并且我们从右上角开始去点,答案还是
2
(
r
+
w
)
2(r+w)
2(r+w),因为增加了
2
2
2条边,去掉的点减少了
2
2
2条边(为什么去点?因为这个矩形的点可能多于
n
n
n)
4、知道第3个性质之后,我们就可以开始凑了,具体怎么凑,每次去掉右上角一个点,都会增加
4
/
2
4/2
4/2条边,如果说还差
2
2
2,但是此时去掉的点贡献是
4
4
4,那么我们先去掉,再把他和某个黑点连起来,就可以删掉多余的
2
2
2
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn = 6e6+1000;
const ll mod = 1e9 + 7;
int n,m;
int vis[500][500];
int main(){
int T,tt=0;cin>>T;
while(T--){
scanf("%d%d",&n,&m);
int r,w,res=0x3f3f3f3f,cnt=0;++tt;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i*j>=n&&2*(i+j)<res){
res=2*(i+j);
r=i,w=j;
}
}
}
if(m%2||m>4*n||res>m){puts("No");continue;}
pair<int,int>grid[100];
for(int i=1;i<=r;i++){
for(int j=1;j<=w;j++){
if(cnt+1<=n){
grid[++cnt]={i,j};
vis[i][j]=tt;
}
}
}
int topk=20,topm=-1;
while(res<m){
int x=grid[cnt].first,y=grid[cnt].second,v=0;
if(vis[x-1][y]==tt)v++;
if(vis[x][y-1]==tt)v++;
if(res+2*v<=m){
res+=2*v;
grid[cnt].first=topk;
topm+=2,grid[cnt].second=topm;
}
else{
res+=2;
grid[cnt]={1,w+1};
}
cnt--;
}
puts("Yes");
for(int i=1;i<=n;i++)printf("%d %d\n",grid[i].first,grid[i].second);
}
}