E. Tree Constructing
time limit per test4 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given three integers
n
n,
d
d and
k
k.
Your task is to construct an undirected tree on
n
n vertices with diameter
d
d and degree of each vertex at most
k
k, or say that it is impossible.
An undirected tree is a connected undirected graph with
n
−
1
n−1 edges.
Diameter of a tree is the maximum length of a simple path (a path in which each vertex appears at most once) between all pairs of vertices of this tree.
Degree of a vertex is the number of edges incident to this vertex (i.e. for a vertex
u
u it is the number of edges
(
u
,
v
)
(u,v) that belong to the tree, where
v
v is any other vertex of a tree).
Input
The first line of the input contains three integers
n
n,
d
d and
k
k (
1
≤
n
,
d
,
k
≤
4
⋅
10
5
1≤n,d,k≤4⋅105).
Output
If there is no tree satisfying the conditions above, print only one word “NO” (without quotes).
Otherwise in the first line print “YES” (without quotes), and then print
n
−
1
n−1 lines describing edges of a tree satisfying the conditions above. Vertices of the tree must be numbered from
1
1 to
n
n. You can print edges and vertices connected by an edge in any order. If there are multiple answers, print any of them.1
Examples
inputCopy
6 3 3
outputCopy
YES
3 1
4 1
1 2
5 2
2 6
inputCopy
6 2 3
outputCopy
NO
inputCopy
10 4 3
outputCopy
YES
2 9
2 10
10 3
3 1
6 10
8 2
4 3
5 6
6 7
inputCopy
8 5 3
outputCopy
YES
2 5
7 2
3 7
3 1
1 6
8 7
4 3
题意:题目给出两个限制条件的d,k。想让构造出一个两节点最远距离为d,每个节点度数不超过k的树。
构造方法有很多,我是从根节点开始构造的。
1、度数是非常好构造的,除了根节点,其余的节点儿子不超过k-1即可(另一度连着其父亲)。
2、如果构造出来的树(视作图)尽可能的中心对称,那么他的两节点最远距离肯定最小(毕竟能放儿子的地方都放上了)。所以可以通过最远距离的奇偶进行分类讨论。
如果最远距离是偶数,那么直接以根节点中心对称构造好了。
如果最远距离是奇数,那么取一条边放在中间,左右以此边为中心,对称构造就好了。
画画图就了然了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
int n,d,k,x;
vector <int>v1,v2;
void add(int u,int v){
v1.push_back(u);
v2.push_back(v);
}
void dfs(int u,int du,int cs){
if(cs){
while(du--){
if(x>=n) return;
x++;
add(u,x);
dfs(x,k-1,cs-1);
}
}
}
int main()
{
scanf("%d %d %d",&n,&d,&k);x=1;
if(n==1||d>=n) {puts("NO");return 0;}
int dd=d/2;
if(d%2==1){
int tmp=n/2-1;
add(1,2);x=2;n-=tmp;
dfs(1,k-1,dd);n+=tmp;
dfs(2,k-1,dd);
}
else{
int tmp=n/2;
n-=tmp;dfs(1,k/2,dd);
n+=tmp;dfs(1,k-k/2,dd);
}
if(x<n) {puts("NO");return 0;}
puts("YES");
for(int i=0;i<n-1;i++){
printf("%d %d\n",v1[i],v2[i]);
}
return 0;
}