• + 3 comments

    Python2 solution

    # Enter your code here. Read input from STDIN. Print output to STDOUT
    # Problem: https://www.interviewstreet.com/challenges/dashboard/#problem/4f6522ab2f425
    
    from heapq import heappush, heappop
    
    INF = 999999999999999
    
    class SegTreeNode(object):
        def __init__(self, left, right, data):
            self.left = left
            self.right = right
            self.data = data
            self.left_child = None
            self.right_child = None
        
        def __repr__(self):
            return "<node left:%d right:%d data:%d>" % (self.left, self.right, self.data)
    
    class SegTree(object):
        def __init__(self, left, right):
            self.root = self.make_tree(left, right)
    
        def make_tree(self, left, right):
            node = SegTreeNode(left, right, INF)
            if left < right:
                mid = (left + right) / 2
                node.left_child = self.make_tree(left, mid)
                node.right_child = self.make_tree(mid + 1, right)
            return node
    
        def _update(self, left, right, val, node):
            if right < node.left or left > node.right:
                return
            if node.left_child and left <= node.left_child.right:
                self._update(left, right, val, node.left_child)
            if node.right_child and right >= node.right_child.left:
                self._update(left, right, val, node.right_child)
            if node.left >= left and node.right <= right:
                node.data = min(node.data, val)
        
        def update(self, left, right, val):
            self._update(left, right, val, self.root)
        
        def _query(self, left, right, node):
            if node is None or right < node.left or left > node.right:
                return INF
            if node.left >= left and node.right <= right:
                return node.data
            return min(self._query(left, right, node.left_child), self._query(left, right, node.right_child))
    
        def query(self, left, right):
            return self._query(left, right, self.root)
    
    def dijkstra(N, S, edges):
        d = [INF for i in range(N)]
        d[S] = 0
        h = []
        heappush(h, (0, S))
        for i in range(N - 1):
            min_dist, k = 0, 0
            if not h: break
            while h:
                min_dist, k = heappop(h)
                if min_dist == d[k]: break
            for j, w in edges[k]:
                if d[j] > d[k] + w:
                    d[j] = d[k] + w
                    heappush(h, (d[j], j))
        return d
    
    def tarjan(N, S, T, edges):
        cnt = 0
        bridges = []
        visit = [0 for i in range(N)]
        low = [N + 1 for i in range(N)]
        ret = [False for i in range(N)]
        q = [0 for i in range(N + 1)]
        q[0] = (S, -1, -1)
        top = 0
        while top >= 0:
            i, father, v = q[top]
            if v == -1:
                ret[i] = (i == T)
                cnt = cnt + 1
                visit[i] = low[i] = cnt
            elif v < len(edges[i]):
                j, w, flag = edges[i][v]
                if flag:
                    if j == q[top + 1][0]:
                        ret[i] = ret[i] or ret[j]
                        if ret[i]: low[i] = min(low[i], low[j])
            v += 1
            q[top] = (i, father, v)
            if v < len(edges[i]):
                j, w, flag = edges[i][v]
                if flag:
                    if not visit[j]:
                        top += 1
                        q[top] = (j, i, -1)
                else:
                    if j != father and visit[j]:
                        low[i] = min(low[i], visit[j])
            else:
                if low[i] == visit[i] and ret[i]:
                    if father >=0:
                        bridges.append((father, i))
                top -= 1
        return bridges
    
    def work(N, S, T, edge_list, ds, dt, OPT, query):
        if OPT >= INF:
            for u, v in query:
                print "Infinity"
            return
        edges = [[] for i in range(N)]
        for u, v, w in edge_list:
            if ds[u] + w == ds[v]:
                edges[u].append((v, w, True))
                edges[v].append((u, w, False))
        bridges = tarjan(N, S, T, edges)
        p = [0 for i in range(N)]
        def bfs(i, part):
            q = [i,]
            head = 0
            while head < len(q):
                i = q[head]
                p[i] = part
                for j, w, flag in edges[i]:
                    if flag and p[j] == 0:
                        q.append(j)
                head += 1
        part = len(bridges) + 1
        bridge_set = {}
        for u, v in bridges:
            bridge_set[(u, v)] = (u, v)
            bridge_set[(v, u)] = (u, v)
            bfs(v, part)
            part -= 1
        bfs(S, part)
        n = len(bridges) + 1
        tree = SegTree(1, n)
        for u, v, w in edge_list:
            if p[u] and p[v] and p[u] < p[v] and bridge_set.get((u, v), None) is None:
                tree.update(p[u], p[v] - 1, ds[u] + w + dt[v])
        def answer(u, v):
            b = bridge_set.get((u, v), None)
            if b is None:
                return OPT
            else:
                return tree.query(p[b[0]], p[b[1]] - 1)
        for u, v in query:
            result = answer(u, v)
            if result < INF:
                print result
            else:
                print "Infinity"
    
    def main():
        N, M = map(int, raw_input().split())
        edges = [[] for i in range(N)]
        edge_list = []
        for i in range(M):
            u, v, w = map(int, raw_input().split())
            edge_list.append((u, v, w))
            edge_list.append((v, u, w))
            edges[u].append((v, w))
            edges[v].append((u, w))
        S, T = map(int, raw_input().split())
        ds = dijkstra(N, S, edges)
        dt = dijkstra(N, T, edges)
        OPT = ds[T]
        query = []
        Q = int(raw_input())
        for i in range(Q):
            u, v = map(int, raw_input().split())
            query.append((u, v))
        work(N, S, T, edge_list, ds, dt, OPT, query)
    main()