CodeForces Round#423 Div2D&Div1B(827B) Solution

来源:互联网 发布:大数据高并发 面试题 编辑:程序博客网 时间:2024/06/06 01:03

题意:要求输出一棵树的形态(即树的边),要求:总共有n个点,其中k个叶子节点(度为1),并且这棵树的直径要最小。

题解:考虑一棵树,先画出一条直径,现在假设这个直径是最小的,那么现在考虑如何向直径链上加入树的所有节点,且不使得树的直径变大,学过均值的同学都知道要找到直径的中点,然后向外延伸一条链(树枝),否则,如果更偏左边一些,那么直径的右链和新加入的链的直径会超过原有直径。而我们又想让一条链可以消耗尽可能少的叶子数量,并且带有尽可能多的节点,那么显然就是没有枝杈的赤裸裸的链最节省叶子节点数。那么现在这棵树的形态一定是:一个根节点,向外辐射出若干条赤裸的链。再来考虑致敬最小这个条件,我们希望每条链平摊最少的节点,那么就平均分就可以了,最后多的几个就分到不同的链上一条链一个就好了。说了半天…………其实就是找一个根节点,然后向外长k个链,转着圈加节点就行了。。

Code:

#include<bits/stdc++.h>using namespace std;#define MAXN 200005int length[MAXN];int n,k;int main(){    cin>>n>>k;    n--;    int delta = n%k;    int length = n/k;    int now =1;    if (delta>=2){        cout<<2*(length+1)<<endl;    }else if (delta==1){        cout<<2*length+1<<endl;    }else{        cout<<2*length<<endl;    }    for (int i=0;i<delta;i++){        now++;        cout<<"1 "<<now<<endl;        for (int j=1;j<length+1;j++){            now++;            cout<<now<<" "<<now-1<<endl;        }    }    for (int i=0;i<k-delta;i++){        now++;        cout<<"1 "<<now<<endl;        for (int j=1;j<length;j++){            now++;            cout<<now<<" "<<now-1<<endl;        }    }    return 0;} 


阅读全文
0 0