今天写一道cf的训练题,第一次感觉到这样一道十分有趣(傻屌)的题目。题目名字叫构造树感觉像是一道考察树的题目,定睛一看明白了这道理和树的关系就像钢铁是怎样炼成的和钢铁行业的一般。
所以为了研究0.3%含碳量的铁和0.5%含碳量的铁那个硬度高我们。。。。不好意思回到题目中我们看这道题题目的意思是。。。什么你说没看到题,奥不好意思鸡冻了那我们就先上题目。tada~~~~
题目
You are given three integers nn, dd and kk.
Your task is to construct an undirected tree on nn vertices with diameter dd and degree of each vertex at most kk, or say that it is impossible.
An undirected tree is a connected undirected graph with n−1n−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 uu it is the number of edges (u,v)(u,v) that belong to the tree, where vv is any other vertex of a tree).
Input
The first line of the input contains three integers nn, dd and kk (1≤n,d,k≤4⋅1051≤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−1n−1 lines describing edges of a tree satisfying the conditions above. Vertices of the tree must be numbered from 11 to nn. You can print edges and vertices connected by an edge in any order. If there are multiple answers, print any of them.1
Examples
Input
6 3 3
Output
YES
3 1
4 1
1 2
5 2
2 6
Input
6 2 3
Output
NO
Input
10 4 3
Output
YES
2 9
2 10
10 3
3 1
6 10
8 2
4 3
5 6
6 7
Input
8 5 3
Output
YES
2 5
7 2
3 7
3 1
1 6
8 7
4 3
好了这就是题目的全部内容,我们首先来分析一下题意,第一首先我们需要构造一个顶点数为n,度数不超过为k,且任意两点之间的距离不超过d。
所以这道题目的约束条件有两个第一是度数k,第二是距离d。而我们所要完成的目标是构造这样一个包含n个顶点的树。看起来我们的操作好像是要从树这个数据结构去寻找思路,但是实际上观察之后便会发现我们没有办法用到任何一条和树有关的知识,反而我们真正需要用到的是递归。
题目要求直径小于d,所以我们首先就来连出一条直径。我们以8 5 3 为例,做出图形,我们看到在端点的部分因为已经是最远
直径所以不能再加顶点,依次向中间每走一步就可以多深入一层。由此我们便可以得出算法。
#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
using namespace std;
// 常量
//const int MAXN = 4e5 + 2;
// 全局变量
int n,d,k;
int id;
vector <pair<int,int>> ans;
//int deep[MAXN],degree[MAXN];
// 函数申明
void dfs(int,int,int);
int main(){
cin >> n >> d >> k;
if((n <= d) || (d > 1 && k < 2)){
cout << "NO" << endl;
return 0;
}
for(int i = 1;i <= d;i++)
ans.push_back(make_pair(i,i + 1));
id = d + 1;
for(int i = 2;i <= d;i++)
dfs(i,0,min(i - 1,d - i + 1));
if(id < n)
cout << "NO" << endl;
else{
cout << "YES" << endl;
for (int i = 0;i < ans.size();i++)
cout << ans[i].first << " " << ans[i].second << endl;
}
return 0;
}
void dfs(int u,int dep,int maxd){
if(maxd == dep){
return;
}
for(int i = 0;i < k - 1 - (dep == 0) && id < n;i++){
ans.push_back(make_pair(u,++id));
dfs(id,dep + 1,maxd);
}
}