New Year Santa Network (Codeforces 500D)
Tags: Others, trees

New Year is coming in Tree World! In this world, as the name implies, there are n cities connected by n - 1 roads, and for any two distinct cities there always exists a path between them. The cities are numbered by integers from 1 to n, and the roads are numbered by integers from 1 to n - 1. Let's define d(u, v) as total length of roads on the path between city u and city v.As an annual event, people in Tree World repairs exactly one road per year. As a result, the length of one road decreases. It is already known that in the i-th year, the length of the ri-th road is going to become wi, which is shorter than its length before. Assume that the current year is year 1.Three Santas are planning to give presents annually to all the children in Tree World. In order to do that, they need some preparation, so they are going to choose three distinct cities c1, c2, c3 and make exactly one warehouse in each city. The k-th (1 ≤ k ≤ 3) Santa will take charge of the warehouse in city ck.It is really boring for the three Santas to keep a warehouse alone. So, they decided to build an only-for-Santa network! The cost needed to build this network equals to d(c1, c2) + d(c2, c3) + d(c3, c1) dollars. Santas are too busy to find the best place, so they decided to choose c1, c2, c3 randomly uniformly over all triples of distinct numbers from 1 to n. Santas would like to know the expected value of the cost needed to build the network.However, as mentioned, each year, the length of exactly one road decreases. So, the Santas want to calculate the expected after each length change. Help them to calculate the value.

Input: The first line contains an integer n (3 ≤ n ≤ 105) — the number of cities in Tree World.Next n - 1 lines describe the roads. The i-th line of them (1 ≤ i ≤ n - 1) contains three space-separated integers ai, bi, li (1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ li ≤ 103), denoting that the i-th road connects cities ai and bi, and the length of i-th road is li.The next line contains an integer q (1 ≤ q ≤ 105) — the number of road length changes.Next q lines describe the length changes. The j-th line of them (1 ≤ j ≤ q) contains two space-separated integers rj, wj (1 ≤ rj ≤ n - 1, 1 ≤ wj ≤ 103). It means that in the j-th repair, the length of the rj-th road becomes wj. It is guaranteed that wj is smaller than the current length of the rj-th road. The same road can be repaired several times.

Output: Output q numbers. For each given change, print a line containing the expected cost needed to build the network in Tree World. The answer will be considered correct if its absolute and relative error doesn't exceed 10 - 6.

Note: Consider the first sample. There are 6 triples: (1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1). Because n = 3, the cost needed to build the network is always d(1, 2) + d(2, 3) + d(3, 1) for all the triples. So, the expected cost equals to d(1, 2) + d(2, 3) + d(3, 1).

Sample Inputs:
3
2 3 5
1 3 3
5
1 4
2 2
1 2
2 1
1 1

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

Sample Outputs:
14.0000000000
12.0000000000
8.0000000000
6.0000000000
4.0000000000

19.6000000000
18.6000000000
16.6000000000
13.6000000000
12.6000000000

Solution (Python):
import sys
import heapq
from collections import defaultdict, deque
readline = sys.stdin.readline

class Graph:

    def __init__(self, V, edges=False, graph=False, directed=False, weighted=False):
        self.V = V
        self.directed = directed
        self.weighted = weighted
        if not graph:
            self.edges = edges
            self.graph = [[] for i in range(self.V)]
            if weighted:
                for (i, j, d) in self.edges:
                    self.graph[i].append((j, d))
                    if not self.directed:
                        self.graph[j].append((i, d))
            else:
                for (i, j) in self.edges:
                    self.graph[i].append(j)
                    if not self.directed:
                        self.graph[j].append(i)
        else:
            self.graph = graph
            self.edges = []
            for i in range(self.V):
                if self.weighted:
                    for (j, d) in self.graph[i]:
                        if self.directed or (not self.directed and i <= j):
                            self.edges.append((i, j, d))
                else:
                    for j in self.graph[i]:
                        if self.directed or (not self.directed and i <= j):
                            self.edges.append((i, j))

    def SS_BFS(self, s, bipartite_graph=False, linked_components=False, parents=False, unweighted_dist=False, weighted_dist=False):
        seen = [False] * self.V
        seen[s] = True
        if linked_components:
            lc = [s]
        if parents:
            ps = [None] * self.V
            ps[s] = s
        if unweighted_dist or bipartite_graph:
            uwd = [float('inf')] * self.V
            uwd[s] = 0
        if weighted_dist:
            wd = [float('inf')] * self.V
            wd[s] = 0
        queue = deque([s])
        while queue:
            x = queue.popleft()
            for y in self.graph[x]:
                if self.weighted:
                    (y, d) = y
                if not seen[y]:
                    seen[y] = True
                    queue.append(y)
                    if linked_components:
                        lc.append(y)
                    if parents:
                        ps[y] = x
                    if unweighted_dist or bipartite_graph:
                        uwd[y] = uwd[x] + 1
                    if weighted_dist:
                        wd[y] = wd[x] + d
        if bipartite_graph:
            bg = [[], []]
            for tpl in self.edges:
                (i, j) = tpl[:2] if self.weighted else tpl
                if type(uwd[i]) == float or type(uwd[j]) == float:
                    continue
                if not uwd[i] % 2 ^ uwd[j] % 2:
                    bg = False
                    break
            else:
                for x in range(self.V):
                    if type(uwd[x]) == float:
                        continue
                    bg[uwd[x] % 2].append(x)
        tpl = ()
        if bipartite_graph:
            tpl += (bg,)
        if linked_components:
            tpl += (lc,)
        if parents:
            tpl += (ps,)
        if unweighted_dist:
            tpl += (uwd,)
        if weighted_dist:
            tpl += (wd,)
        if len(tpl) == 1:
            tpl = tpl[0]
        return tpl

    def AP_BFS(self, bipartite_graph=False, linked_components=False, parents=False):
        seen = [False] * self.V
        if bipartite_graph:
            bg = [None] * self.V
            cnt = -1
        if linked_components:
            lc = []
        if parents:
            ps = [None] * self.V
        for s in range(self.V):
            if seen[s]:
                continue
            seen[s] = True
            if bipartite_graph:
                cnt += 1
                bg[s] = (cnt, 0)
            if linked_components:
                lc.append([s])
            if parents:
                ps[s] = s
            queue = deque([s])
            while queue:
                x = queue.popleft()
                for y in self.graph[x]:
                    if self.weighted:
                        (y, d) = y
                    if not seen[y]:
                        seen[y] = True
                        queue.append(y)
                        if bipartite_graph:
                            bg[y] = (cnt, bg[x][1] ^ 1)
                        if linked_components:
                            lc[-1].append(y)
                        if parents:
                            ps[y] = x
        if bipartite_graph:
            bg_ = bg
            bg = [[[], []] for i in range(cnt + 1)]
            for tpl in self.edges:
                (i, j) = tpl[:2] if self.weighted else tpl
                if not bg_[i][1] ^ bg_[j][1]:
                    bg[bg_[i][0]] = False
            for x in range(self.V):
                if bg[bg_[x][0]]:
                    bg[bg_[x][0]][bg_[x][1]].append(x)
        tpl = ()
        if bipartite_graph:
            tpl += (bg,)
        if linked_components:
            tpl += (lc,)
        if parents:
            tpl += (ps,)
        if len(tpl) == 1:
            tpl = tpl[0]
        return tpl

    def SS_DFS(self, s, bipartite_graph=False, cycle_detection=False, directed_acyclic=False, euler_tour=False, linked_components=False, parents=False, postorder=False, preorder=False, subtree_size=False, topological_sort=False, unweighted_dist=False, weighted_dist=False):
        seen = [False] * self.V
        finished = [False] * self.V
        if directed_acyclic or cycle_detection or topological_sort:
            dag = True
        if euler_tour:
            et = []
        if linked_components:
            lc = []
        if parents or cycle_detection or subtree_size:
            ps = [None] * self.V
            ps[s] = s
        if postorder or topological_sort:
            post = []
        if preorder:
            pre = []
        if subtree_size:
            ss = [1] * self.V
        if unweighted_dist or bipartite_graph:
            uwd = [float('inf')] * self.V
            uwd[s] = 0
        if weighted_dist:
            wd = [float('inf')] * self.V
            wd[s] = 0
        stack = [(s, 0)] if self.weighted else [s]
        while stack:
            if self.weighted:
                (x, d) = stack.pop()
            else:
                x = stack.pop()
            if not seen[x]:
                seen[x] = True
                stack.append((x, d) if self.weighted else x)
                if euler_tour:
                    et.append(x)
                if linked_components:
                    lc.append(x)
                if preorder:
                    pre.append(x)
                for y in self.graph[x]:
                    if self.weighted:
                        (y, d) = y
                    if not seen[y]:
                        stack.append((y, d) if self.weighted else y)
                        if parents or cycle_detection or subtree_size:
                            ps[y] = x
                        if unweighted_dist or bipartite_graph:
                            uwd[y] = uwd[x] + 1
                        if weighted_dist:
                            wd[y] = wd[x] + d
                    elif not finished[y]:
                        if (directed_acyclic or cycle_detection or topological_sort) and dag:
                            dag = False
                            if cycle_detection:
                                cd = (y, x)
            elif not finished[x]:
                finished[x] = True
                if euler_tour:
                    et.append(~x)
                if postorder or topological_sort:
                    post.append(x)
                if subtree_size:
                    for y in self.graph[x]:
                        if y == ps[x]:
                            continue
                        ss[x] += ss[y]
        if bipartite_graph:
            bg = [[], []]
            for tpl in self.edges:
                (i, j) = tpl[:2] if self.weighted else tpl
                if type(uwd[i]) == float or type(uwd[j]) == float:
                    continue
                if not uwd[i] % 2 ^ uwd[j] % 2:
                    bg = False
                    break
            else:
                for x in range(self.V):
                    if type(uwd[x]) == float:
                        continue
                    bg[uwd[x] % 2].append(x)
        tpl = ()
        if bipartite_graph:
            tpl += (bg,)
        if cycle_detection:
            if dag:
                cd = []
            else:
                (y, x) = cd
                cd = self.Route_Restoration(y, x, ps)
            tpl += (cd,)
        if directed_acyclic:
            tpl += (dag,)
        if euler_tour:
            tpl += (et,)
        if linked_components:
            tpl += (lc,)
        if parents:
            tpl += (ps,)
        if postorder:
            tpl += (post,)
        if preorder:
            tpl += (pre,)
        if subtree_size:
            tpl += (ss,)
        if topological_sort:
            if dag:
                tp_sort = post[::-1]
            else:
                tp_sort = []
            tpl += (tp_sort,)
        if unweighted_dist:
            tpl += (uwd,)
        if weighted_dist:
            tpl += (wd,)
        if len(tpl) == 1:
            tpl = tpl[0]
        return tpl

    def AP_DFS(self, bipartite_graph=False, cycle_detection=False, directed_acyclic=False, euler_tour=False, linked_components=False, parents=False, postorder=False, preorder=False, topological_sort=False):
        seen = [False] * self.V
        finished = [False] * self.V
        if bipartite_graph:
            bg = [None] * self.V
            cnt = -1
        if directed_acyclic or cycle_detection or topological_sort:
            dag = True
        if euler_tour:
            et = []
        if linked_components:
            lc = []
        if parents or cycle_detection:
            ps = [None] * self.V
        if postorder or topological_sort:
            post = []
        if preorder:
            pre = []
        for s in range(self.V):
            if seen[s]:
                continue
            if bipartite_graph:
                cnt += 1
                bg[s] = (cnt, 0)
            if linked_components:
                lc.append([])
            if parents:
                ps[s] = s
            stack = [(s, 0)] if self.weighted else [s]
            while stack:
                if self.weighted:
                    (x, d) = stack.pop()
                else:
                    x = stack.pop()
                if not seen[x]:
                    seen[x] = True
                    stack.append((x, d) if self.weighted else x)
                    if euler_tour:
                        et.append(x)
                    if linked_components:
                        lc[-1].append(x)
                    if preorder:
                        pre.append(x)
                    for y in self.graph[x]:
                        if self.weighted:
                            (y, d) = y
                        if not seen[y]:
                            stack.append((y, d) if self.weighted else y)
                            if bipartite_graph:
                                bg[y] = (cnt, bg[x][1] ^ 1)
                            if parents or cycle_detection:
                                ps[y] = x
                        elif not finished[y]:
                            if directed_acyclic and dag:
                                dag = False
                                if cycle_detection:
                                    cd = (y, x)
                elif not finished[x]:
                    finished[x] = True
                    if euler_tour:
                        et.append(~x)
                    if postorder or topological_sort:
                        post.append(x)
        if bipartite_graph:
            bg_ = bg
            bg = [[[], []] for i in range(cnt + 1)]
            for tpl in self.edges:
                (i, j) = tpl[:2] if self.weighted else tpl
                if not bg_[i][1] ^ bg_[j][1]:
                    bg[bg_[i][0]] = False
            for x in range(self.V):
                if bg[bg_[x][0]]:
                    bg[bg_[x][0]][bg_[x][1]].append(x)
        tpl = ()
        if bipartite_graph:
            tpl += (bg,)
        if cycle_detection:
            if dag:
                cd = []
            else:
                (y, x) = cd
                cd = self.Route_Restoration(y, x, ps)
            tpl += (cd,)
        if directed_acyclic:
            tpl += (dag,)
        if euler_tour:
            tpl += (et,)
        if linked_components:
            tpl += (lc,)
        if parents:
            tpl += (ps,)
        if postorder:
            tpl += (post,)
        if preorder:
            tpl += (pre,)
        if topological_sort:
            if dag:
                tp_sort = post[::-1]
            else:
                tp_sort = []
            tpl += (tp_sort,)
        if len(tpl) == 1:
            tpl = tpl[0]
        return tpl

    def Tree_Diameter(self, weighted=False):

        def Farthest_Point(u):
            dist = self.SS_BFS(u, weighted_dist=True) if weighted else self.SS_BFS(u, unweighted_dist=True)
            fp = 0
            for i in range(self.V):
                if dist[fp] < dist[i]:
                    fp = i
            return (fp, dist[fp])
        (u, d) = Farthest_Point(0)
        (v, d) = Farthest_Point(u)
        return (u, v, d)

    def SCC(self):
        reverse_graph = [[] for i in range(self.V)]
        for tpl in self.edges:
            (i, j) = tpl[:2] if self.weighted else tpl
            reverse_graph[j].append(i)
        postorder = self.AP_DFS(postorder=True)
        scc = []
        seen = [False] * self.V
        for s in postorder[::-1]:
            if seen[s]:
                continue
            queue = deque([s])
            seen[s] = True
            lst = []
            while queue:
                x = queue.popleft()
                lst.append(x)
                for y in reverse_graph[x]:
                    if self.weighted:
                        y = y[0]
                    if not seen[y]:
                        seen[y] = True
                        queue.append(y)
            scc.append(lst)
        return scc

    def Build_LCA(self, s):
        (self.euler_tour, self.parents, depth) = self.SS_DFS(s, euler_tour=True, parents=True, unweighted_dist=True)
        self.dfs_in_index = [None] * self.V
        self.dfs_out_index = [None] * self.V
        for (i, x) in enumerate(self.euler_tour):
            if x >= 0:
                self.dfs_in_index[x] = i
            else:
                self.dfs_out_index[~x] = i
        self.ST = Segment_Tree(2 * self.V, lambda x, y: min(x, y), float('inf'))
        lst = [None] * 2 * self.V
        for i in range(2 * self.V):
            if self.euler_tour[i] >= 0:
                lst[i] = depth[self.euler_tour[i]]
            else:
                lst[i] = depth[self.parents[~self.euler_tour[i]]]
        self.ST.Build(lst)

    def LCA(self, a, b):
        m = min(self.dfs_in_index[a], self.dfs_in_index[b])
        M = max(self.dfs_in_index[a], self.dfs_in_index[b])
        x = self.euler_tour[self.ST.Fold_Index(m, M + 1)]
        if x >= 0:
            return x
        else:
            return self.parents[~x]

    def Dijkstra(self, s, route_restoration=False):
        dist = [float('inf')] * self.V
        dist[s] = 0
        hq = [(0, s)]
        if route_restoration:
            parents = [None] * self.V
            parents[s] = s
        while hq:
            (dx, x) = heapq.heappop(hq)
            if dist[x] < dx:
                continue
            for (y, dy) in self.graph[x]:
                if dist[y] > dx + dy:
                    dist[y] = dx + dy
                    if route_restoration:
                        parents[y] = x
                    heapq.heappush(hq, (dist[y], y))
        if route_restoration:
            return (dist, parents)
        else:
            return dist

    def Bellman_Ford(self, s, route_restoration=False):
        dist = [float('inf')] * self.V
        dist[s] = 0
        if route_restoration:
            parents = [s] * self.V
        for _ in range(self.V - 1):
            for (i, j, d) in self.edges:
                if dist[j] > dist[i] + d:
                    dist[j] = dist[i] + d
                    if route_restoration:
                        parents[j] = i
                if not self.directed and dist[i] > dist[j] + d:
                    dist[i] = dist[j] + d
                    if route_restoration:
                        parents[i] = j
        negative_cycle = []
        for (i, j, d) in self.edges:
            if dist[j] > dist[i] + d:
                negative_cycle.append(j)
            if not self.directed and dist[i] > dist[j] + d:
                negative_cycle.append(i)
        if negative_cycle:
            is_negative_cycle = [False] * self.V
            for i in negative_cycle:
                if is_negative_cycle[i]:
                    continue
                else:
                    queue = deque([i])
                    is_negative_cycle[i] = True
                    while queue:
                        x = queue.popleft()
                        for (y, d) in self.graph[x]:
                            if not is_negative_cycle[y]:
                                queue.append(y)
                                is_negative_cycle[y] = True
                                if route_restoration:
                                    parents[y] = x
            for i in range(self.V):
                if is_negative_cycle[i]:
                    dist[i] = -float('inf')
        if route_restoration:
            return (dist, parents)
        else:
            return dist

    def Warshall_Floyd(self, route_restoration=False):
        dist = [[float('inf')] * self.V for i in range(self.V)]
        for i in range(self.V):
            dist[i][i] = 0
        if route_restoration:
            parents = [[j for j in range(self.V)] for i in range(self.V)]
        for (i, j, d) in self.edges:
            if dist[i][j] > d:
                dist[i][j] = d
                if route_restoration:
                    parents[i][j] = i
            if not self.directed and dist[j][i] > d:
                dist[j][i] = d
                if route_restoration:
                    parents[j][i] = j
        for k in range(self.V):
            for i in range(self.V):
                for j in range(self.V):
                    if dist[i][j] > dist[i][k] + dist[k][j]:
                        dist[i][j] = dist[i][k] + dist[k][j]
                        if route_restoration:
                            parents[i][j] = parents[k][j]
        for i in range(self.V):
            if dist[i][i] < 0:
                for j in range(self.V):
                    if dist[i][j] != float('inf'):
                        dist[i][j] = -float('inf')
        if route_restoration:
            return (dist, parents)
        else:
            return dist

    def Route_Restoration(self, s, g, parents):
        route = [g]
        while s != g and parents[g] != g:
            g = parents[g]
            route.append(g)
        route = route[::-1]
        return route

    def Kruskal(self):
        UF = UnionFind(self.V)
        sorted_edges = sorted(self.edges, key=lambda x: x[2])
        minimum_spnning_tree = []
        for (i, j, d) in sorted_edges:
            if not UF.Same(i, j):
                UF.Union(i, j)
                minimum_spnning_tree.append((i, j, d))
        return minimum_spnning_tree

    def Ford_Fulkerson(self, s, t):
        max_flow = 0
        residual_graph = [defaultdict(int) for i in range(self.V)]
        if self.weighted:
            for (i, j, d) in self.edges:
                if not d:
                    continue
                residual_graph[i][j] += d
                if not self.directed:
                    residual_graph[j][i] += d
        else:
            for (i, j) in self.edges:
                residual_graph[i][j] += 1
                if not self.directed:
                    residual_graph[j][i] += 1
        while True:
            parents = [None] * self.V
            parents[s] = s
            seen = [False] * self.V
            seen[s] = True
            queue = deque([s])
            while queue:
                x = queue.popleft()
                for y in residual_graph[x].keys():
                    if not seen[y]:
                        seen[y] = True
                        queue.append(y)
                        parents[y] = x
                        if y == t:
                            tt = t
                            while tt != s:
                                residual_graph[parents[tt]][tt] -= 1
                                residual_graph[tt][parents[tt]] += 1
                                if not residual_graph[parents[tt]][tt]:
                                    residual_graph[parents[tt]].pop(tt)
                                tt = parents[tt]
                            max_flow += 1
                            break
                else:
                    continue
                break
            else:
                break
        return max_flow

    def BFS(self, s):
        seen = [False] * self.V
        seen[s] = True
        queue = deque([s])
        while queue:
            x = queue.popleft()
            for y in self.graph[x]:
                if self.weighted:
                    (y, d) = y
                if not seen[y]:
                    seen[y] = True
                    queue.append(y)
        return

    def DFS(self, s):
        seen = [False] * self.V
        finished = [False] * self.V
        stack = [(s, 0)] if self.weighted else [s]
        while stack:
            if self.weighted:
                (x, d) = stack.pop()
            else:
                x = stack.pop()
            if not seen[x]:
                seen[x] = True
                stack.append((x, d) if self.weighted else x)
                for y in self.graph[x]:
                    if self.weighted:
                        (y, d) = y
                    if not seen[y]:
                        stack.append((y, d) if self.weighted else y)
            elif not finished[x]:
                finished[x] = True
        return
N = int(readline())
edges = []
cost = []
for _ in range(N - 1):
    (u, v, c) = map(int, readline().split())
    u -= 1
    v -= 1
    edges.append((u, v))
    cost.append(c)
G = Graph(N, edges=edges)
(parents, size) = G.SS_DFS(0, parents=True, subtree_size=True)
cnt = [None] * (N - 1)
for i in range(N - 1):
    (u, v) = edges[i]
    if v == parents[u]:
        (u, v) = (v, u)
    cnt[i] = size[v] * (N - size[v])
ans = sum((cost[i] * cnt[i] for i in range(N - 1)))
Q = int(readline())
for _ in range(Q):
    (i, c) = map(int, readline().split())
    i -= 1
    ans -= cnt[i] * (cost[i] - c)
    cost[i] = c
    print(ans * 6 / (N * (N - 1)))

Solution (Python):
from queue import Queue
import sys
cost = []

def readarray():
    return map(int, input().split(' '))
n = int(input())
graph = [[] for i in range(n)]
for i in range(n - 1):
    (u, v, c) = readarray()
    (u, v) = (u - 1, v - 1)
    cost.append(c)
    graph[u].append((v, i))
    graph[v].append((u, i))
order = []
used = [0] * n
q = [0] * (n + n)
qh = qt = 0
used[qh] = 1
qh += 1
while qt < qh:
    v = q[qt]
    qt += 1
    order.append(v)
    for (to, e) in graph[v]:
        if used[to]:
            continue
        used[to] = 1
        q[qh] = to
        qh += 1
order.reverse()
sz = [0 for x in range(n)]
for v in order:
    sz[v] = 1
    for (to, e) in graph[v]:
        sz[v] += sz[to]
''
distanceSum = 0.0
edgeMult = [0] * n
for v in range(n):
    for (to, e) in graph[v]:
        x = min(sz[v], sz[to])
        edgeMult[e] = x
        distanceSum += 1.0 * cost[e] * x * (n - x)
distanceSum /= 2.0
queryCnt = int(input())
ans = []
for i in range(queryCnt):
    (x, y) = readarray()
    x -= 1
    distanceSum -= 1.0 * cost[x] * edgeMult[x] * (n - edgeMult[x])
    cost[x] = y
    distanceSum += 1.0 * cost[x] * edgeMult[x] * (n - edgeMult[x])
    ans.append('%.10lf' % (distanceSum / n / (n - 1) * 6.0))
print('\n'.join(ans))

Solution (Python):
from queue import Queue
import sys
cost = []

def readarray():
    return map(int, input().split(' '))
n = int(input())
graph = [[] for i in range(n)]
for i in range(n - 1):
    (u, v, c) = readarray()
    (u, v) = (u - 1, v - 1)
    cost.append(c)
    graph[u].append((v, i))
    graph[v].append((u, i))
order = []
used = [0] * n
q = [0] * (n + n)
qh = qt = 0
used[qh] = 1
qh += 1
while qt < qh:
    v = q[qt]
    qt += 1
    order.append(v)
    for (to, e) in graph[v]:
        if used[to]:
            continue
        used[to] = 1
        q[qh] = to
        qh += 1
order.reverse()
sz = [0 for x in range(n)]
for v in order:
    sz[v] = 1
    for (to, e) in graph[v]:
        sz[v] += sz[to]
''
distanceSum = 0.0
edgeMult = [0] * n
for v in range(n):
    for (to, e) in graph[v]:
        x = min(sz[v], sz[to])
        edgeMult[e] = x
        distanceSum += 1.0 * cost[e] * x * (n - x)
distanceSum /= 2.0
queryCnt = int(input())
ans = []
for i in range(queryCnt):
    (x, y) = readarray()
    x -= 1
    distanceSum -= 1.0 * cost[x] * edgeMult[x] * (n - edgeMult[x])
    cost[x] = y
    distanceSum += 1.0 * cost[x] * edgeMult[x] * (n - edgeMult[x])
    ans.append('%.10lf' % (distanceSum / n / (n - 1) * 6.0))
print('\n'.join(ans))