Codeforces Round #423 (Div. 2) D High Load 贪心,树

来源:互联网 发布:3米直尺道路检测数据 编辑:程序博客网 时间:2024/06/06 03:21

CF传送门

题意:

1. 给n个点,要求建立一棵只有k个端点树(即k个叶节点)

2. 求该树的最远两个端点的最短距离(尽量去建立满树)

3. 输出距离和点与点之间的连线

题解:

1. 根据要求可以知道要尽量去建立满树(就是根节点要尽量分出多点枝条,看图解)

2. 难点在于找到两个最远端点的距离 和 根节点(注释中所说的分点)

3. 对于距离有四种情况:

    ~只有两个端点时树是直的,距离=n-1。这是个特殊情况

    ~当总节点数对总端点数求模时,模是1时代表所有枝一样长,模是0时代表有一条枝较短其他枝较长(和情况4类似)

    ~当模是2时表示只有一条枝较长(较长的必须算入距离啊)

    ~当模大于3时表示至少有两条枝较长

4. 对于根节点,画几个图就可以找到规律为 距离/2+1 了

5. 说了那么多就是希望多动手,数据结构(这里是树)和贪心结合的题就这样



以下是我的AC代码:

//多画几棵不同的简单的树比较一下就有规律了//最重要是形成的树的最远距离和分点的判断#include <cstdio>using namespace std;int main(){    int n,k,num=2;                          //k是端点    scanf("%d%d",&n,&k);    int dis;    if(k==2)                                //树只有两个端点时成一条直线        dis=n-1;    else if(n%k<=1)                         //等于1时就是一棵满树,等于0时表示只有有一条枝短1        dis=2*(n/k);    else if(n%k==2)                         //只有一条枝长1        dis=2*(n/k)+1;    else                                    //大于或等于两条枝长1        dis=2*(n/k+1);    printf("%d\n",dis);                     //距离    int div=dis/2+1;                        //分点    for(int i=1;i<div;i++)                  //分点前组合        printf("%d %d\n",i,num++);    for(int i=1;i<=k-1;i++)                 //分点情况        printf("%d %d\n",div,num++);    for(int i=div+1;num<=n;i++)             //分点后的分支情况        printf("%d %d\n",i,num++);    return 0;}

原创粉丝点击