提出 #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 | ||
| 結果 |
|
| セット名 | テストケース |
|---|---|
| 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 |