Gardening Friends (Codeforces 1822F)
Tags: DP, trees

Two friends, Alisa and Yuki, planted a tree with $$$n$$$ vertices in their garden. A tree is an undirected graph without cycles, loops, or multiple edges. Each edge in this tree has a length of $$$k$$$. Initially, vertex $$$1$$$ is the root of the tree.Alisa and Yuki are growing the tree not just for fun, they want to sell it. The cost of the tree is defined as the maximum distance from the root to a vertex among all vertices of the tree. The distance between two vertices $$$u$$$ and $$$v$$$ is the sum of the lengths of the edges on the path from $$$u$$$ to $$$v$$$.The girls took a course in gardening, so they know how to modify the tree. Alisa and Yuki can spend $$$c$$$ coins to shift the root of the tree to one of the neighbors of the current root. This operation can be performed any number of times (possibly zero). Note that the structure of the tree is left unchanged; the only change is which vertex is the root.The friends want to sell the tree with the maximum profit. The profit is defined as the difference between the cost of the tree and the total cost of operations. The profit is cost of the tree minus the total cost of operations.Help the girls and find the maximum profit they can get by applying operations to the tree any number of times (possibly zero).

Input: The first line of the input contains one integer $$$t$$$ ($$$1 \le t \le 10^4$$$) — the number of test cases. The description of the test cases follows.The first line of each test case contains integers $$$n$$$, $$$k$$$, $$$c$$$ ($$$2 \le n \le 2 \cdot 10^5$$$; $$$1 \le k, c \le 10^9$$$) — the number of vertices in the tree, the length of each edge, and the cost of the operation.The next $$$n - 1$$$ lines of the test case contain pairs of integers $$$u_i$$$, $$$v_i$$$ ($$$1 \le u_i, v_i \le n$$$) — the edges of the graph. These edges form a tree.The sum of the values of $$$n$$$ over all test cases does not exceed $$$2 \cdot 10^5$$$.

Output: For each test case, output a single integer — the maximum profit that Yuki and Alisa can get.


Sample Inputs:
4
3 2 3
2 1
3 1
5 4 1
2 1
4 2
5 4
3 4
6 5 3
4 1
6 1
2 6
5 1
3 2
10 6 4
1 3
1 9
9 7
7 6
6 4
9 2
2 8
8 5
5 10

Sample Outputs:
2
12
17
32

Solution (Python):
""""""
import sys

def input():
    return sys.stdin.readline()[:-1]
t = int(input())
from collections import deque

def bfs(G, s):
    inf = 10 ** 30
    D = [inf] * len(G)
    D[s] = 0
    dq = deque()
    dq.append(s)
    while dq:
        x = dq.popleft()
        for y in G[x]:
            if D[y] > D[x] + 1:
                D[y] = D[x] + 1
                dq.append(y)
    return D
for _ in range(t):
    (n, k, c) = map(int, input().split())
    G = [[] for i in range(n)]
    for i in range(n - 1):
        (u, v) = map(lambda x: int(x) - 1, input().split())
        G[u].append(v)
        G[v].append(u)
    D = bfs(G, 0)
    d = max(D)
    x = D.index(d)
    D2 = bfs(G, x)
    d2 = max(D2)
    y = D2.index(d2)
    D3 = bfs(G, y)
    print(max([k * max(D2[i], D3[i]) - c * D[i] for i in range(n)]))

Solution (Python):
import sys

def input():
    return sys.stdin.readline()[:-1]
t = int(input())
from collections import deque

def bfs(G, s):
    inf = 10 ** 30
    D = [inf] * len(G)
    D[s] = 0
    dq = deque()
    dq.append(s)
    while dq:
        x = dq.popleft()
        for y in G[x]:
            if D[y] > D[x] + 1:
                D[y] = D[x] + 1
                dq.append(y)
    return D
for _ in range(t):
    (n, k, c) = map(int, input().split())
    G = [[] for i in range(n)]
    for i in range(n - 1):
        (u, v) = map(lambda x: int(x) - 1, input().split())
        G[u].append(v)
        G[v].append(u)
    D = bfs(G, 0)
    d = max(D)
    x = D.index(d)
    D2 = bfs(G, x)
    d2 = max(D2)
    y = D2.index(d2)
    D3 = bfs(G, y)
    print(max([k * max(D2[i], D3[i]) - c * D[i] for i in range(n)]))

Solution (Python):
from collections import deque
from sys import gettrace, stdin
if not gettrace():

    def input():
        return next(stdin)[:-1]

def solve():
    (n, k, c) = map(int, input().split())
    adj = [[] for _ in range(n + 1)]
    for _ in range(n - 1):
        (u, v) = map(int, input().split())
        adj[u].append(v)
        adj[v].append(u)
    q = deque([1])
    depth = [0] * (n + 1)
    parent = [0] * (n + 1)
    dord = [1]
    while q:
        v = q.popleft()
        for a in adj[v]:
            if a != parent[v]:
                depth[a] = depth[v] + 1
                parent[a] = v
                dord.append(a)
                q.append(a)
    if c >= k:
        print(depth[dord[-1]] * k)
        return
    cd = [[0, 0] for _ in range(n + 1)]
    for v in dord[::-1]:
        if cd[parent[v]][0] < cd[v][0] + 1:
            cd[parent[v]][1] = cd[parent[v]][0]
            cd[parent[v]][0] = cd[v][0] + 1
        elif cd[parent[v]][1] < cd[v][0] + 1:
            cd[parent[v]][1] = cd[v][0] + 1
    res = max(((cd[v][0] + cd[v][1]) * k - (depth[v] + cd[v][1]) * c for v in range(1, n + 1)))
    print(res)

def main():
    for _ in range(int(input())):
        solve()
if __name__ == '__main__':
    main()