您的位置:首页 > 其它

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

2017-07-12 22:37 465 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: