提出 #41139446


ソースコード 拡げる

#include <atcoder/all>
using namespace atcoder;
#include <bits/stdc++.h>
#include <cassert>
using namespace std;
using ll = long long;
const double pi = 3.14159265359;
const ll INF = 1LL << 60;

template<class T> inline bool chmin(T& a, T b){ if (a > b){a = b; return true;} return false;}
template<class T> inline bool chmax(T& a, T b){ if (a < b){a = b; return true;} return false;}

//using mint = modint998244353;
using mint = modint1000000007;
//using mint = modint;  // mint::set_mod(p); later
//using mint = static_modint<1000000009>;

int N, K;
vector<vector<int>> edges;

// dp[i][j][k] : 部分木 i において、j 本のパスを選ぶ選び方のうち、頂点 i の次数が k であるものの個数
mint dp[1005][55][3];

void dfs(int x, int par)
{
  vector<int> child;
  for (int i : edges[x]){
    if (i != par){
      child.push_back(i);
      dfs(i, x);
    }
  }

  int nchild = (int) child.size();

  // dp2[x][y][z] :  x 個の子までみたとき、y 本のパスを選ぶ選び方のうち、頂点 i へのパスの本数が z
  vector<vector<vector<mint>>> dp2(nchild + 1,
				   vector<vector<mint>>(K + 1,
							vector<mint>(3)));

  dp2[0][0][0] = 1;

  for (int i = 0; i < nchild; i++){
    int l = child[i];
    for (int j = 0; j <= K; j++){
      for (int k = 0; k <= 2; k++){
	for (int m = 0; m <= K; m++){ // ループ条件を m + j <= K としたくなるが我慢
	  for (int n = 0; n <= 2; n++){
	    // (A) x - l の辺はつながない場合
	    if (j + m <= K){
	      dp2[i+1][j+m][k] += dp2[i][j][k] * dp[l][m][n];
	    }

	    // (B) x - l をつなぐ場合は、(k, n) の組み合わせで4通り
	    // (B-1) (k, n) = (1, 1)
	    //       2 つのパスが点 x でつながる
	    if (k == 1 && n == 1 && j + m - 1 >= 0 && j + m - 1 <= K){
	      dp2[i+1][j+m-1][2] += dp2[i][j][k] * dp[l][m][n];
	    }

	    // (B-2) (k, n) = (1, 0)
	    //       k 側のパスのうち1つが伸びる
	    if (k == 1 && n == 0 && j+m <= K){
	      dp2[i+1][j+m][k+1] += dp2[i][j][k] * dp[l][m][n];
	    }
	    
	    // (B-3) (k, n) = (0, 1)
	    //       n 側のパスのうち1つが伸びる
	    if (k == 0 && n == 1 && j + m <= K){
	      dp2[i+1][j+m][1] += dp2[i][j][k] * dp[l][m][n];
	    }

	    // (B-4) (k, n) = (0, 0)
	    //       x - l  が孤立パスになる
	    if (k == 0 && n == 0 && j + m + 1 <= K){
	      dp2[i+1][j+m+1][1] += dp2[i][j][k] * dp[l][m][n];
	    }
	  }
	}
      }
    }
  }

  for (int i = 0; i <= K; i++){
    for (int j = 0; j <= 2; j++){
      dp[x][i][j] = dp2[nchild][i][j];
    }
  }
}

int main()
{
  cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);

  cin >> N >> K;
  edges.resize(N);

  for (int i = 0; i < N - 1; i++){
    int a, b;
    cin >> a >> b;
    a--; b--;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }

  dfs(0, -1);

  mint ans = 0;
  for (int i = 0; i <= 2; i++){
    ans += dp[0][K][i];
  }

  cout << ans.val() << endl;
  return 0;
}

提出情報

提出日時
問題 P - うなぎ
ユーザ unnohideyuki
言語 C++ (GCC 9.2.1)
得点 6
コード長 3082 Byte
結果 AC
実行時間 103 ms
メモリ 4512 KiB

ジャッジ結果

セット名 All
得点 / 配点 6 / 6
結果
AC × 9
セット名 テストケース
All 00, 01, 02, 03, 04, 05, 06, 90, 91
ケース名 結果 実行時間 メモリ
00 AC 103 ms 4512 KiB
01 AC 9 ms 4360 KiB
02 AC 98 ms 4248 KiB
03 AC 98 ms 4304 KiB
04 AC 98 ms 4408 KiB
05 AC 98 ms 4244 KiB
06 AC 99 ms 4316 KiB
90 AC 6 ms 4144 KiB
91 AC 3 ms 4168 KiB