E - Tree Constructing CF训练赛

        今天写一道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);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值