Codeforces Round #333 (Div. 1) D. Acyclic Organic Compounds trie树合并

D. Acyclic Organic Compounds
 

You are given a tree T with n vertices (numbered 1 through n) and a letter in each vertex. The tree is rooted at vertex 1.

Let's look at the subtree Tv of some vertex v. It is possible to read a string along each simple path starting at v and ending at some vertex in Tv (possibly v itself). Let's denote the number of distinct strings which can be read this way as .

Also, there's a number cv assigned to each vertex v. We are interested in vertices with the maximum value of .

You should compute two statistics: the maximum value of  and the number of vertices v with the maximum .

Input

The first line of the input contains one integer n (1 ≤ n ≤ 300 000) — the number of vertices of the tree.

The second line contains n space-separated integers ci (0 ≤ ci ≤ 109).

The third line contains a string s consisting of n lowercase English letters — the i-th character of this string is the letter in vertex i.

The following n - 1 lines describe the tree T. Each of them contains two space-separated integers u and v (1 ≤ u, v ≤ n) indicating an edge between vertices u and v.

It's guaranteed that the input will describe a tree.

Output

Print two lines.

On the first line, print  over all 1 ≤ i ≤ n.

On the second line, print the number of vertices v for which .

Examples
input
10
1 2 7 20 20 30 40 50 50 50
cacabbcddd
1 2
6 8
7 2
6 2
5 4
5 9
3 10
2 5
2 3
output
51
3
Note

In the first sample, the tree looks like this:

The sets of strings that can be read from individual vertices are:

Finally, the values of  are:

In the second sample, the values of  are (5, 4, 2, 1, 1, 1). The distinct strings read in T2 are ; note that can be read down to vertices 3 or 4.

 

trie树合并

比较考验代码能力

显然我就比较low

这份代码是cf抠来的

#include<iostream>
#include<vector>
#include<cassert>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 300000 + 10;
const int V = N * 15;

int n, tot;
int ch[V][26], size[V];
int c[N];
int father[N];
vector<int> adj[N];
char label[N];

int merge(int u, int v)
{
    if (u < 0) return v;
    if (v < 0) return u;
    int t = tot ++;
    size[t] = 1;
    for(int c = 0; c < 26; ++ c) {
        ch[t][c] = merge(ch[u][c], ch[v][c]);
        if (ch[t][c] >= 0) {
            size[t] += size[ch[t][c]];
        }
    }
    return t;
}

void dfs(int u)
{
    for(int c = 0; c < 26; ++ c) {
        ch[u][c] = -1;
    }
    for(int e = 0; e < adj[u].size(); ++e) {
        int v = adj[u][e];
        if (v == father[u]) continue;
        father[v] = u;
        dfs(v);
        int lab = label[v] - 'a';
        ch[u][lab] = merge(ch[u][lab], v);
    }
    size[u] = 1;
    for(int x = 0; x < 26; ++ x) {
        if (ch[u][x] >= 0) {
            size[u] += size[ch[u][x]];
        }
    }
    c[u] += size[u];
}

void solve()
{
    cin >> n;
    for(int i = 0; i < n; ++ i) {
        scanf("%d", c + i);
    }
    scanf("%s", label);
    for(int i = 0; i < n - 1; ++ i) {
        int u, v;
        scanf("%d%d", &u, &v);
        --u, --v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    father[0] = -1;
    tot = n;
    dfs(0);
    int ret = *max_element(c, c + n);
    int cnt = 0;
    for(int i = 0; i < n; ++ i) {
        if (c[i] == ret) ++ cnt;
    }
    cout << ret << ' ' << cnt << endl;
}

int main()
{
    solve();
    return 0;
}

 

 

posted @ 2016-09-22 20:11  meekyan  阅读(252)  评论(0编辑  收藏  举报