Codeforces1003E-构造一个树

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题意:

 原题目描述在最下面。
 给你n, k, d。问是否能构造出一颗树,其有n个节点,直径为k,每个点的度数不超过d。若能,则输出YES 并输出任意符合条件的解,反之输出NO

思路:

 我的写法是先特判能否构造出一条直径来,若不能则直接输出NO。构造出了直径之后,就枚举这条直径上的点,进行dfs。
控制直径:
控制直径上每个节点能往下延伸的长度。长度 = min(dep[i] - 1, k + 1 - dep[i])
控制度数:
还要控制每个节点还能增加的分叉数量。数量 = d - du[i]

 搜索的过程中记录一共使用了多少个节点,如果已经有n个节点了就返回。如果始终不能达到n个节点就输出NO,反之输出任意解。

AC代码:

#include<bits/stdc++.h>
#define mk make_pair
using namespace std;
typedef long long LL;
const int inf=2e9+1e8+1234;
const LL linf=8e18+9e17;
const int N = 4e5+7;
const int mod = 998244353;
int n, k, d, tot;//直径不超过k,每个度数不超过d
int du[N], dep[N];
vector<pair<int, int> >ans;
void dfs(int u, int remain){
  if(remain == 0 || du[u] >= d || tot == n)return;
  int _du = du[u];
  //printf("u = %d, remain =  %d, du =  %d, dep = %d\n", u, remain, du[u], dep[u]);
  for(int i = 0; i < d - _du; ++i){
    ans.push_back(mk(u, ++tot));
    dep[tot] = dep[u] + 1;
    du[tot]++;du[u]++;
    if(tot>=n)return;
    dfs(tot, remain - 1);
    if(tot>=n)return;
  }
}
int main(int argc, char const *argv[]){
  while(~scanf("%d%d%d", &n, &k, &d)){
    if(k>=n){//特判
      printf("NO\n");
      continue;
    }
    memset(du, 0, sizeof(du));
    memset(dep, 0, sizeof(dep));
    ans.clear();
    du[0] = du[1] = -1;
    for(int i = 1; i <= k + 1; ++i){
      du[i]++;du[i-1]++;
      dep[i] = i;
      if(i>1)ans.push_back(mk(i - 1, i));
    }
    tot = k + 1;
    for(int i = 1; i <= k + 1; ++i){
      dfs(i, min(dep[i] - 1, k + 1 - dep[i]));
    }
    if(tot != n || (k > 1 && d == 1)){
      printf("NO\n");
    }else{
      printf("YES\n");
      for(auto x: ans){
        printf("%d %d\n", x.first, x.second);
      }
    }
  }
  return 0;
}


原题目描述:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_39599067/article/details/81057126
今日推荐