Guest User

http://blog.blogzhang.com/posts/u7cbl27dsrpjbzjw/

a guest
Jan 11th, 2015
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.20 KB | None | 0 0
  1. import fileinput, math
  2.  
  3. ###          ###
  4. # utility func #
  5. ###          ###
  6.  
  7. dbug = True
  8.  
  9. def pd(s, label=''):
  10.     global dbug
  11.     if dbug:
  12.         header = 'debug:'
  13.         if label != '':
  14.             header += ' (%s)\t' % label
  15.         print header, s
  16.  
  17. def stoi(s):
  18.     return([ int(x) for x in s.split() ])
  19.  
  20. def perm(n, k, wheels=True):
  21.     if wheels:
  22.         assert(n > 0)
  23.         assert(k > 0)
  24.     return math.factorial(n) / math.factorial(k)
  25.  
  26. def comb(n, k, wheels=True):
  27.     if wheels:
  28.         assert(n > 0)
  29.         assert(k > 0)
  30.         assert(n - k > 0)
  31.     return perm(n, k, False) / math.factorial(n - k)
  32.  
  33. def tol(actual, expected, tolerance=10 ** -9):
  34.     if type(actual) != type([]):
  35.         (actual, expected) = ([ actual ], [ expected ])
  36.     r = [ expected[i] - tolerance <= actual[i] <= expected[i] + tolerance for i in xrange(len(actual)) ]
  37.     return sum(r) == len(r)
  38.  
  39. def btod(b):
  40.     return b * 2 - 1
  41.  
  42. def _sigma(f):
  43.     return f * (f + 1) / 2
  44.  
  45. # sum(x from i to f)
  46. def sigma(i, f, wheels=True):
  47.     if wheels:
  48.         assert(i >= 0)
  49.         assert(f >= 0)
  50.     return _sigma(f) - _sigma(i - 1)
  51.  
  52. def ps(l, wheels=True):
  53.     if wheels:
  54.         assert(len(l) > 0)
  55.     r = [ l[0] ] * len(l)
  56.     for i in xrange(1, len(l)):
  57.         r[i] = l[i] + r[i - 1]
  58.     return r
  59.  
  60. def test_utilities():
  61.     assert(stoi('1 2 3\n') == [ 1, 2, 3 ])
  62.     assert(stoi('') == stoi('\n') == [])
  63.     assert(perm(10, 5) == 30240)
  64.     assert(comb(10, 5) == 252)
  65.     assert(tol(0.0, 0.0) == tol(0.0, 0.1, tolerance=0.1) == tol(0.0, 10, tolerance=10) == True)
  66.     assert(tol(0.0, 0.1) == tol(0.0, 0.1, tolerance=0.1 - 10 ** -9) == False)
  67.     assert(_sigma(1) == 1)
  68.     assert(_sigma(10) == 55)
  69.     assert(sigma(1, 10) == 55)
  70.     assert(sigma(3, 10) == 52)
  71.     assert(sigma(10, 10) == 10)
  72.     assert(sigma(10, 11) == 21)
  73.     assert(ps([ 1 ]) == [ 1 ])
  74.     assert(ps([ 1, 2, 3, 4, 5 ]) == [ 1, 3, 6, 10, 15 ])
  75.     assert(btod(0) == -1)
  76.     assert(btod(1) == 1)
  77.  
  78. ###          ###
  79. # code follows #
  80. ###          ###
  81.  
  82. # args = [ 'line 1', 'line 2', ... ]
  83. def proc_input(args):
  84.     n = int(args[0])
  85.     e = []
  86.     c = []
  87.     for l in args[1:n]:
  88.         e.append(stoi(l))
  89.     q = int(args[n])
  90.     for l in args[n + 1:]:
  91.         c.append(stoi(l))
  92.     return(n, e, c)
  93.  
  94. from collections import defaultdict
  95. adj_list = defaultdict(list)
  96. CACHE = defaultdict(int)
  97.  
  98. # recursive DFS doesn't work so well in Python with recursion > 500
  99. #   cf. http://codeforces.com/contest/500/submission/9334488
  100. def dfs():
  101.     is_visited = defaultdict(int)
  102.     # build my own stack
  103.     from collections import deque
  104.     # calc subtree size, given root node and parent
  105.     global adj_list, CACHE
  106.  
  107.     # build the order in which we will inspect the nodes
  108.     o = []
  109.  
  110.     # scratch queue
  111.     s = deque([ 1 ])
  112.     while len(s):
  113.         n = s.popleft()
  114.         o.append(n)
  115.         is_visited[n] = 1
  116.         for c in adj_list[n]:
  117.             if is_visited[c]:
  118.                 continue
  119.             s.append(c)
  120.  
  121.     # and reverse order -- look at the leaves first
  122.     o.reverse()
  123.     for n in o:
  124.         CACHE[n] = 1
  125.         for c in adj_list[n]:
  126.             # if c == p: CACHE[c] isn't computed yet, and thus adds nothing
  127.             CACHE[n] += CACHE[c]
  128.  
  129.     return CACHE[1]
  130.  
  131. # credit to http://codeforces.com/contest/500/submission/9326111 and
  132. #   http://codeforces.com/blog/entry/15488
  133. def solve(args, verbose=False):
  134.     global adj_list, CACHE
  135.     adj_list = defaultdict(list)
  136.     CACHE = defaultdict(int)
  137.     (n, edges, changes) = proc_input(args)
  138.     FAC = 3.0 / n / (n - 1)
  139.     for (a, b, w) in edges:
  140.         adj_list[a].append(b)
  141.         adj_list[b].append(a)
  142.     dfs()
  143.     S = 0.0
  144.     for (a, b, w) in edges:
  145.         # find subtree
  146.         n_A = min(CACHE[a], CACHE[b])
  147.         # find nodes in the remaining tree
  148.         n_B = n - n_A
  149.         S += 2 * w * n_A * n_B
  150.     results = []
  151.     for (r, wp) in changes:
  152.         (a, b, w) = edges[r - 1]
  153.         edges[r - 1] = (a, b, wp)
  154.         n_A = min(CACHE[a], CACHE[b])
  155.         n_B = n - n_A
  156.         S -= 2 * (w - wp) * n_A * n_B
  157.         results.append(FAC * S)
  158.     if verbose:
  159.         for r in results:
  160.             print r
  161.     return results
  162.  
  163. def test():
  164.     assert(solve([ '3', '2 3 5', '1 3 3', '5', '1 4', '2 2', '1 2', '2 1', '1 1' ], verbose=True) == [ 14, 12, 8, 6, 4 ])
  165.     assert(tol(solve([ '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' ], verbose=True), [ 19.6, 18.6, 16.6, 13.6, 12.6 ]))
  166.  
  167. if __name__ == '__main__':
  168.     from sys import argv
  169.     if argv.pop() == 'test':
  170.         test_utilities()
  171.         test()
  172.     else:
  173.         dbug = False
  174.         solve(list(fileinput.input()), verbose=True)
Add Comment
Please, Sign In to add comment