Keshi in Search of AmShZ (Codeforces 1694E)
Tags: Others, shortest paths

AmShZ has traveled to Italy from Iran for the Thom Yorke concert. There are $$$n$$$ cities in Italy indexed from $$$1$$$ to $$$n$$$ and $$$m$$$ directed roads indexed from $$$1$$$ to $$$m$$$. Initially, Keshi is located in the city $$$1$$$ and wants to go to AmShZ's house in the city $$$n$$$. Since Keshi doesn't know the map of Italy, AmShZ helps him to see each other as soon as possible.In the beginning of each day, AmShZ can send one of the following two messages to Keshi: AmShZ sends the index of one road to Keshi as a blocked road. Then Keshi will understand that he should never use that road and he will remain in his current city for the day. AmShZ tells Keshi to move. Then, Keshi will randomly choose one of the cities reachable from his current city and move there. (city $$$B$$$ is reachable from city $$$A$$$ if there's an out-going road from city $$$A$$$ to city $$$B$$$ which hasn't become blocked yet). If there are no such cities, Keshi will remain in his current city.Note that AmShZ always knows Keshi's current location. AmShZ and Keshi want to find the smallest possible integer $$$d$$$ for which they can make sure that they will see each other after at most $$$d$$$ days. Help them find $$$d$$$.

Input: The first line of the input contains two integers $$$n$$$ and $$$m$$$ $$$(2 \le n \le 2 \cdot 10^5, 1 \le m \le 2 \cdot 10^5)$$$  — the number of cities and roads correspondingly.The $$$i$$$-th line of the following $$$m$$$ lines contains two integers $$$v_i$$$ and $$$u_i$$$ $$$(1 \le v_i , u_i \le n,v_i \neq u_i)$$$, denoting a directed road going from city $$$v_i$$$ to city $$$u_i$$$.It is guaranteed that there is at least one route from city $$$1$$$ to city $$$n$$$. Note that there may be more than one road between a pair of cities in each direction.

Output: Output the smallest possible integer $$$d$$$ to make sure that AmShZ and Keshi will see each other after at most $$$d$$$ days.

Note: In the first sample, it's enough for AmShZ to send the second type of message.In the second sample, on the first day, AmShZ blocks the first road. So the only reachable city from city $$$1$$$ will be city $$$4$$$. Hence on the second day, AmShZ can tell Keshi to move and Keshi will arrive at AmShZ's house.It's also possible for AmShZ to tell Keshi to move for two days.

Sample Inputs:
2 1
1 2

4 4
1 2
1 4
2 4
1 4

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

Sample Outputs:
1

2

4

Solution (Python):
from heapq import heappop, heappush
import math
(n, m) = map(int, input().split())
lst = [[] for i in range(n + 1)]
paths = [0] * (n + 1)
for i in range(m):
    (a, b) = map(int, input().split())
    lst[b].append(a)
    paths[a] += 1
arr = []
arr.append((0, n))
days = [math.inf] * (n + 1)
days[n] = 0
mark = [False] * (n + 1)
while arr:
    ele = heappop(arr)
    if mark[ele[1]]:
        continue
    mark[ele[1]] = True
    for i in lst[ele[1]]:
        if ele[0] + paths[i] < days[i]:
            days[i] = ele[0] + paths[i]
            heappush(arr, (days[i], i))
        paths[i] -= 1
print(days[1])

Solution (Python):
import heapq
input = __import__('sys').stdin.readline
(n, m) = map(int, input().split())
deg = [0] * n
rev_adj = [[] for _ in range(n)]
for _ in range(m):
    (u, v) = map(lambda x: int(x) - 1, input().split())
    deg[u] += 1
    rev_adj[v].append(u)
dist = [10 ** 6] * n
dist[-1] = 0
queue = []
heapq.heappush(queue, (0, n - 1))
while len(queue) > 0:
    (d, u) = heapq.heappop(queue)
    if d > dist[u]:
        continue
    for v in rev_adj[u]:
        if dist[v] > dist[u] + deg[v]:
            dist[v] = dist[u] + deg[v]
            heapq.heappush(queue, (dist[v], v))
        deg[v] -= 1
print(dist[0])

Solution (Python):
import decimal
import gc
import heapq
import math
import os
import random
import sys
from collections import Counter, deque, defaultdict
from fractions import Fraction
from io import BytesIO, IOBase
import bisect
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = 'x' in file.mode or 'r' not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b'\n') + (not b)
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            (self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode('ascii'))
        self.read = lambda : self.buffer.read().decode('ascii')
        self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def isPrime(n):
    if n <= 1:
        return False
    if n <= 3:
        return True
    if n % 2 == 0 or n % 3 == 0:
        return False
    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i = i + 6
    return True

def lcm(a, b):
    return a * b // math.gcd(a, b)

def ciel(a, b):
    x = a // b
    if a % b == 0:
        return x
    return x + 1

def ints_get():
    return map(int, input().strip().split())

def list_get():
    return list(map(int, sys.stdin.readline().strip().split()))

def chars_get():
    return list(map(str, sys.stdin.readline().strip().split()))

def ipn():
    return int(input())

def bootstrap(f, stack=[]):

    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to
    return wrappedfunc

def main():
    for _ in range(1):
        (n, m) = ints_get()
        dic = [[] for _ in range(n + 1)]
        co = [0 for _ in range(n + 1)]
        for _ in range(m):
            (u, v) = ints_get()
            dic[v].append(u)
            co[u] += 1
        que = [(0, n)]
        d = [10 ** 15] * n
        d[n - 1] = 0
        while len(que) != 0:
            (cost, v) = heapq.heappop(que)
            if d[v - 1] < cost:
                continue
            for i in dic[v]:
                co[i] -= 1
            for i in dic[v]:
                if d[i - 1] > cost + 1 + co[i]:
                    d[i - 1] = cost + 1 + co[i]
                    heapq.heappush(que, (d[i - 1], i))
        print(d[0])
    return
if __name__ == '__main__':
    main()