Cerinta completa

Jenny loves experimenting with trees. Her favorite tree has nodes connected by edges, and each edge is unit in length. She wants to cut a subtree (i.e., a connected part of the original tree) of radius from this tree by performing the following two steps:

  1. Choose a node, , from the tree.
  2. Cut a subtree consisting of all nodes which are not further than units from node .

For example, the blue nodes in the diagram below depict a subtree centered at that has radius :

image

Given , , and the definition of Jenny’s tree, find and print the number of different subtrees she can cut out. Two subtrees are considered to be different if they are not isomorphic.

Input Format

The first line contains two space-separated integers denoting the respective values of and .
Each of the next subsequent lines contains two space-separated integers, and , describing a bidirectional edge in Jenny’s tree having length .

Constraints

Subtasks

For of the max score:

Output Format

Print the total number of different possible subtrees.

Sample Input 0

7 1
1 2
1 3
1 4
1 5
2 6
2 7

Sample Output 0

3

Explanation 0

In the diagram below, blue nodes denote the possible subtrees:

image

The last subtrees are considered to be the same (i.e., they all consist of two nodes connected by one edge), so we print as our answer.

Sample Input 1

7 3
1 2
2 3
3 4
4 5
5 6
6 7

Sample Output 1

4

Explanation 1

In the diagram below, blue nodes denote the possible subtrees:

image

Here, we have four possible different subtrees.


Limbajul de programare folosit: cpp14

Cod:

#include <bits/stdc++.h>


#include <fstream>
#include <sstream>

#include <vector>
#include <set>
#include <bitset>
#include <map>
#include <deque>
#include <string>

#include <algorithm>
#include <numeric>

#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>

#define pb push_back
#define pbk pop_back
#define mp make_pair
#define fs first
#define sc second
#define all(x) (x).begin(), (x).end()
#define foreach(i, a) for (__typeof((a).begin()) i = (a).begin(); i != (a).end(); ++i)
#define len(a) ((int) (a).size())

#ifdef CUTEBMAING
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define eprintf(...) 42
#endif

using namespace std;

typedef long long int64;
typedef long double ld;
typedef unsigned long long lint;

const int inf = (1 << 30) - 1;
const int64 linf = (1ll << 62) - 1;
const int N = 1e5 + 100;

int n, r;
vector<int> g[N];
bool used[N];

void dfsMark(int v, int p = -1, int d = 0) {
    if (d > r) {
        return;
    }
    used[v] = true;
    for (int to : g[v]) {
        if (p != to) {
            dfsMark(to, v, d + 1);
        }
    }
}

int way[N], wayLen = 0;
int dist[N];

void findDist(int v, int p = -1, int d = 0) {
    if (!used[v]) {
        return ;
    }
    dist[v] = d;
    for (int to : g[v]) {
        if (to != p) {
            findDist(to, v, d + 1);
        }
    }
}

bool findWay(int v, int x, int p = -1) {
    if (!used[v]) {
        return false;
    }
    way[wayLen++] = v;
    if (v == x) {
        return true;
    }
    for (int to : g[v]) {
        if (p != to && findWay(to, x, v)) {
            return true;
        }
    }
    wayLen--;
    return false;
}

vector<int> findCenters(int v) {
    fill_n(dist, n, -inf);
    findDist(v);
    v = max_element(dist, dist + n) - dist;
    findDist(v);
    int to = max_element(dist, dist + n) - dist;
    wayLen = 0;
    assert(findWay(v, to));
    if (wayLen % 2 == 0) {
        return { way[wayLen / 2 - 1], way[wayLen / 2] };
    }
    return { way[wayLen / 2] };
}

int64 rnd[N];

inline int64 myrand() {
    int64 res = 0;
    for (int i = 0; i < 4; i++) {
        res <<= 16;
        res += rand();
    }
    return res;
}

inline int64 dfsHash(int v, int p = -1) {
    vector<int64> go;
    for (int to : g[v]) {
        if (to != p && used[to]) {
            go.pb(dfsHash(to, v));
        }
    }
    sort(all(go));
    int64 res = 423929593294391LL;
    for (int i = 0; i < len(go); i++) {
        res ^= go[i] * rnd[i];
    }
    return res;
}

int main() {
#ifdef XCODE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    srand(-1);
    for (int i = 0; i < N; i++) {
        rnd[i] = myrand();
    }
    cin >> n >> r;
    assert(1 <= n && n <= 3000);
    assert(0 <= r && r <= 3000);
    for (int i = 0; i < n - 1; i++) {
        int u, v; scanf("%d%d", &u, &v), u--, v--;
        g[u].pb(v), g[v].pb(u);
    }
    vector<int64> res;
    for (int i = 0; i < n; i++) {
        fill_n(used, n, false);
        dfsMark(i);
        auto centers = findCenters(i);
        if (len(centers) == 1) {
            int64 h = dfsHash(centers.back());
            eprintf("v = %d; center = %d; hash = %lldn", i, centers.back(), h);
            res.pb(h);
        } else {
            int64 h1 = dfsHash(centers[0], centers[1]), h2 = dfsHash(centers[1], centers[0]);
            if (h1 > h2) {
                swap(h1, h2);
            }
            int64 h = (8418348238341LL * h1) ^ (4847574732881394LL * h2);
            res.pb(h);
            eprintf("v = %d; centers = %d, %d; hash = %lldn", i, centers[0], centers[1], h);
        }
    }
    sort(all(res));
    for (auto i : res) {
        eprintf("%lld ", i);
    }
    eprintf("n");
    res.resize(unique(all(res)) - res.begin());
    cout << len(res) << endl;
    return 0;
}

Scor obtinut: 1.0

Submission ID: 464652973

Link challenge: https://www.hackerrank.com/challenges/jenny-subtrees/problem

Jenny’s Subtrees