2200专项:E. Tree Constructing(树构造)

原题: http://codeforces.com/problemset/problem/1003/E

题意: 用n个点构造一棵树,每点的度最大为k,直径为d(最长简单路径)

解析:

首先定框架,点1下面,右边是d/2,左边是d-d/2,然后dfs插入即可。注意d的路径点数为d+1。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define repp(i,b,a) for(int i=b;i>=a;i--)
#define LL long long
#define out {cout<<"NO\n";return 0;}
#define yes {cout<<"YES\n";}
#define pb push_back

const int maxn=4e5+5;
vector<int>Son[maxn];
int ct=0;
int n,d,k;

void In(int p,int dep,int have){
    if(ct==n)return;
    if(dep==0)return;
    rep(i,1,k-have){
        Son[p].pb(++ct);
        In(ct,dep-1,1);
        if(ct==n)return;
    }
}

void dfs(int p){
    rep(i,0,Son[p].size()-1){
        cout<<p<<' '<<Son[p][i]<<endl;
        dfs(Son[p][i]);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    //2 1 3
    cin>>n>>d>>k;

    if(n==1||n<=d)out
    if(k==1){
        if(n>2)out
        else{
            if(d!=1)out
            else{
                yes
                cout<<"1 2\n";
                return 0;
            }
        }
    }
    if(d==1){
        if(n!=2)out
        else{
            yes
            cout<<"1 2\n";
            return 0;
        }
    }
    //n多
    ct++;// p1
    ct++;Son[1].pb(2);// p2
    ct++;Son[1].pb(3);// p3

    int l=d/2,r=l;
    if(d%2)l++;

    vector<int>Vl,Vr;
    for(int now=2,i=1;i<l;i++){
        Son[now].pb(++ct);now=ct;
        Vl.pb(now);
    }
    for(int now=3,i=1;i<r;i++){
        Son[now].pb(++ct);now=ct;
        Vr.pb(now);
    }

    In(2,l-1,2);
    In(3,r-1,2);
    rep(i,0,Vl.size()-1)In(Vl[i],l-2-i,2);
    rep(i,0,Vr.size()-1)In(Vr[i],r-2-i,2);
    int son1=2;
    while(ct<n&&son1<k){
        son1++;
        Son[1].pb(++ct);
        In(ct,r-1,1);
    }
    if(ct<n)out;
    yes;
    dfs(1);
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/89295393