Kitty's Calculations on a Tree


Problem Statement :


Kitty has a tree, T , consisting of n nodes where each node is uniquely labeled from  1 to n . Her friend Alex gave her q sets, where each set contains k distinct nodes. Kitty needs to calculate the following expression on each set:

where:

{ u ,v } denotes an unordered pair of nodes belonging to the set.
 dist(u , v) denotes the number of edges on the unique (shortest) path between nodes  and .
Given T and q sets of k  distinct nodes, calculate the expression for each set. For each set of nodes, print the value of the expression modulo 10^9 + 7  on a new line.


Input Format

The first line contains two space-separated integers, the respective values of n (the number of nodes in tree T ) and  q (the number of nodes in the query set).
Each of the n - 1  subsequent lines contains two space-separated integers, a and b, that describe an undirected edge between nodes  and .
The 2 * q subsequent lines define each set over two lines in the following format:

The first line contains an integer, k  , the size of the set.
The second line contains  k space-separated integers, the set's elements.

Output Format

Print q lines of output where each line i contains the expression for the ith query, modulo 10^9 + 7.



Solution :



title-img


                            Solution in C :

In C ++ :




#include <bits/stdc++.h>

using namespace std;

const int MOD=1000000007;
int N, Q;
vector<int> adj[200001];
vector<int> adj2[200001];
int P[18][200001];
int depth[200001];
int in[200001];
int out[200001];
int now;
int A[400001];
int mul[200001];
long long sum[200001];

void dfs(int u, int p)
{
    P[0][u]=p;
    for(int i=1; i<18; i++)
        P[i][u]=P[i-1][P[i-1][u]];
    in[u]=++now;
    for(auto& v: adj[u]) if(v!=p)
    {
        depth[v]=depth[u]+1;
        dfs(v, u);
    }
    out[u]=now;
}

int lca(int u, int v)
{
    if(depth[u]<depth[v])
        swap(u, v);
    for(int i=17; i>=0; i--) if(depth[P[i][u]]>=depth[v])
        u=P[i][u];
    if(u==v)
        return u;
    for(int i=17; i>=0; i--) if(P[i][u]!=P[i][v])
        u=P[i][u], v=P[i][v];
    return P[0][u];
}

int dfs2(int u, long long tot)
{
    int ret=0;
    sum[u]=u*mul[u];
    for(auto& v: adj2[u])
    {
        ret=(ret+dfs2(v, tot))%MOD;
        sum[u]+=sum[v];
    }
    for(auto& v: adj2[u])
        ret=(ret+1LL*((tot-sum[v])%MOD)
                    *(sum[v]%MOD)%MOD
                    *(depth[v]-depth[u])%MOD)%MOD;
    return ret;
}

int main()
{
    scanf("%d%d", &N, &Q);
    for(int i=0; i<N-1; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    dfs(1, 1);
    while(Q--)
    {
        int K;
        scanf("%d", &K);
        long long tot=0;
        for(int i=0; i<K; i++)
            scanf("%d", A+i), mul[A[i]]=1, tot+=A[i];
        sort(A, A+K, [](int a, int b) {
            return in[a]<in[b];
        });
        for(int i=0; i<K-1; i++)
            A[i+K]=lca(A[i], A[i+1]);
        sort(A, A+2*K-1);
        int M=unique(A, A+2*K-1)-A;
        sort(A, A+M, [](int a, int b) {
            return out[a]-in[a]>out[b]-in[b];
        });
        int root=A[0];
        map<int, int> m;
        m[in[root]]=root;
        for(int i=1; i<M; i++)
        {
            int u=A[i];
            auto it=m.upper_bound(in[u]);
            assert(it!=m.begin());
            --it;
            int p=it->second;
            adj2[p].push_back(u);
            //printf("%d -> %d\n", p, u);
            m[in[u]]=u;
            if(out[u]<out[p] && (!m.count(out[u]+1) || P[0][m[out[u]+1]]!=p))
                m[out[u]+1]=p;
        }
        printf("%d\n", dfs2(root, tot));
        for(int i=0; i<M; i++)
            adj2[A[i]].clear(), mul[A[i]]=0;
    }
    return 0;
}








In Java :




import java.util.Arrays;
import java.util.Scanner;

public class KittysCalc {
	
	public static final long constant = 1000000007;
	
	public static void main(String[] args) {
		
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	int queries = sc.nextInt();
	int[] parents = new int[n+1];
	long[] children = new long[n+1];
	boolean[] valuesSet = new boolean[n+1];
	long valuesSum = 0;
	long sum = 0;
	int a, b;
	for(int i = 0; i < n-1; i++) {
		a = sc.nextInt();
		b = sc.nextInt();
		if(a < b) {
			parents[b] = a;
		} else {
			parents[a] = b;
		}
	}
	parents[1] = 0;
		
	for(int i = 0; i < queries; i++) {
		int k = sc.nextInt();
		Arrays.fill(valuesSet, false);
		Arrays.fill(children, 0);
		valuesSum = 0;
		for(int j = 0; j < k; j++) {
			a = sc.nextInt();
			valuesSum += a;
			valuesSet[a] = true;
		}
		sum = 0;
		for (int j = n; j > 0; j--) {
		long c = children[j];
		if (valuesSet[j]) {
			c += j;
		}
		if (c > 0) {
		long x = ((c % constant) * ((valuesSum - c) % constant)) % constant;
		if (constant - sum < x) {
			sum -= constant;
		}
		sum += x;
			}
	children[parents[j]] += c;
			}
System.out.println(sum);
		}
		sc.close();
	}

}








In Python3 :





#!/usr/bin/env python3

def put(d, a, b):
    if a in d: d[a].append(b)
    else: d[a] = [b]

def main():
    for n in ns[::-1]:
        r = [tt[s] for s in tree[n] if s != f[n]]
        bst = {s: [gl[n], n, 0] for s in queries[n]}
        if r:
            o = max(range(len(r)), key=lambda a: len(r[a]))
            if len(r[o]) > len(bst): r[o], bst = bst, r[o]
        ry = {}
        for ae in r:
            for y, v in ae.items():
                put(ry, y, v)
        for y, r in ry.items():
            eq, z, t = 0, 0, 0
            if len(r) == 1 and y not in bst:
                bst[y] = r[0]
                continue
            if y in bst: r.append(bst.pop(y))
            for d, v, c in r:
                eq += (d - gl[n]) * v + c
                z += v
            for d, v, c in r:
                c += (d - gl[n]) * v
                diff = (eq - c) * v
                t += diff
            returns[y] += t
            bst[y] = (gl[n], z, eq)
        tt[n] = bst
    
def locate():
    q = [r]
    level = 0
    while q:
        level += 1
        tmp = []
        ns.extend(q)
        for n in q:
            for s in tree[n]:
                if s not in f:
                    f[s] = n
                    gl[s] = level
                    tmp.append(s)
        q = tmp
        
tree = {}
tt = {}
n, q = map(int, input().split())
returns = [0] * q
for _ in range(n - 1):
    a, b = map(int, input().split())
    put(tree, a, b)
    put(tree, b, a)
queries = {a: set() for a in tree}
for y in range(q):
    input()
    for x in map(int, input().split()): queries[x].add(y)
r = next(iter(tree))
ns = []
f = {r: None}
gl = {r: 0}
locate()
main()
for s in returns: print(s % (10**9 + 7))
                        








View More Similar Problems

Array-DS

An array is a type of data structure that stores elements of the same type in a contiguous block of memory. In an array, A, of size N, each memory location has some unique index, i (where 0<=i<N), that can be referenced as A[i] or Ai. Reverse an array of integers. Note: If you've already solved our C++ domain's Arrays Introduction challenge, you may want to skip this. Example: A=[1,2,3

View Solution →

2D Array-DS

Given a 6*6 2D Array, arr: 1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 An hourglass in A is a subset of values with indices falling in this pattern in arr's graphical representation: a b c d e f g There are 16 hourglasses in arr. An hourglass sum is the sum of an hourglass' values. Calculate the hourglass sum for every hourglass in arr, then print t

View Solution →

Dynamic Array

Create a list, seqList, of n empty sequences, where each sequence is indexed from 0 to n-1. The elements within each of the n sequences also use 0-indexing. Create an integer, lastAnswer, and initialize it to 0. There are 2 types of queries that can be performed on the list of sequences: 1. Query: 1 x y a. Find the sequence, seq, at index ((x xor lastAnswer)%n) in seqList.

View Solution →

Left Rotation

A left rotation operation on an array of size n shifts each of the array's elements 1 unit to the left. Given an integer, d, rotate the array that many steps left and return the result. Example: d=2 arr=[1,2,3,4,5] After 2 rotations, arr'=[3,4,5,1,2]. Function Description: Complete the rotateLeft function in the editor below. rotateLeft has the following parameters: 1. int d

View Solution →

Sparse Arrays

There is a collection of input strings and a collection of query strings. For each query string, determine how many times it occurs in the list of input strings. Return an array of the results. Example: strings=['ab', 'ab', 'abc'] queries=['ab', 'abc', 'bc'] There are instances of 'ab', 1 of 'abc' and 0 of 'bc'. For each query, add an element to the return array, results=[2,1,0]. Fun

View Solution →

Array Manipulation

Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in the array. Example: n=10 queries=[[1,5,3], [4,8,7], [6,9,1]] Queries are interpreted as follows: a b k 1 5 3 4 8 7 6 9 1 Add the valu

View Solution →