結果
| 問題 |
No.1364 [Renaming] Road to Cherry from Zelkova
|
| コンテスト | |
| ユーザー |
lam6er
|
| 提出日時 | 2025-03-20 20:53:01 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 625 ms / 2,500 ms |
| コード長 | 4,597 bytes |
| コンパイル時間 | 358 ms |
| コンパイル使用メモリ | 81,716 KB |
| 実行使用メモリ | 196,064 KB |
| 最終ジャッジ日時 | 2025-03-20 20:53:26 |
| 合計ジャッジ時間 | 18,611 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 45 |
ソースコード
import sys
from collections import deque
MOD = 10**9 + 7
def main():
input = sys.stdin.read().split()
idx = 0
N = int(input[idx])
idx += 1
M = int(input[idx])
idx += 1
edges = []
for _ in range(M):
u = int(input[idx])
v = int(input[idx+1])
l = int(input[idx+2])
a = int(input[idx+3])
edges.append((u, v, l, a))
idx += 4
# Step 1: Compute S (0-reachable)
adj_forward = [[] for _ in range(N+1)]
for u, v, _, _ in edges:
adj_forward[u].append(v)
S = [False] * (N + 1)
q = deque()
q.append(0)
S[0] = True
while q:
u = q.popleft()
for v in adj_forward[u]:
if not S[v]:
S[v] = True
q.append(v)
# Step 2: Compute T (N-reachable in reverse graph)
adj_backward = [[] for _ in range(N+1)]
for u, v, _, _ in edges:
adj_backward[v].append(u)
T = [False] * (N + 1)
q = deque()
q.append(N)
T[N] = True
while q:
u = q.popleft()
for v in adj_backward[u]:
if not T[v]:
T[v] = True
q.append(v)
# Step 3: Build partial graph (u in S and v in T)
partial_edges = []
adj_partial = [[] for _ in range(N+1)]
for u, v, l, a in edges:
if S[u] and T[v]:
adj_partial[u].append(v)
partial_edges.append((u, v, l, a))
# Check if there's any path from 0 to N
visited = [False] * (N + 1)
q = deque()
q.append(0)
visited[0] = True
reach_N = False
while q:
u = q.popleft()
if u == N:
reach_N = True
break
for v in adj_partial[u]:
if not visited[v]:
visited[v] = True
q.append(v)
if not reach_N:
print(0)
return
# Step 4: Build adjacency and reverse adjacency for partial graph
adj_part = [[] for _ in range(N+1)]
rev_adj_part = [[] for _ in range(N+1)]
for u, v, l, a in partial_edges:
adj_part[u].append(v)
rev_adj_part[v].append(u)
# Kosaraju's algorithm to find SCCs in partial graph
visited = [False] * (N+1)
order = []
# First pass to get finishing order
for u in range(N+1):
if S[u] and any(T[v] for v in adj_partial[u]) and not visited[u]:
stack = [(u, False)]
while stack:
node, processed = stack.pop()
if processed:
order.append(node)
continue
if visited[node]:
continue
visited[node] = True
stack.append((node, True))
for v in reversed(adj_part[node]):
if not visited[v]:
stack.append((v, False))
# Second pass to get components
visited = [False] * (N+1)
components = []
for node in reversed(order):
if not visited[node]:
stack = [node]
visited[node] = True
component = [node]
while stack:
u = stack.pop()
for v in rev_adj_part[u]:
if not visited[v]:
visited[v] = True
stack.append(v)
component.append(v)
components.append(component)
# Check if any component has size >=2
for component in components:
if len(component) >= 2:
print("INF")
return
# Step 5: Topological sort on partial graph
edge_info = [[] for _ in range(N+1)]
for u, v, l, a in partial_edges:
edge_info[u].append((v, l, a))
in_degree = [0] * (N+1)
for u in range(N+1):
for v, _, _ in edge_info[u]:
in_degree[v] += 1
q = deque()
for u in range(N+1):
if in_degree[u] == 0 and S[u] and T[u]:
q.append(u)
topo_order = []
while q:
u = q.popleft()
topo_order.append(u)
for v, _, _ in edge_info[u]:
in_degree[v] -= 1
if in_degree[v] == 0:
q.append(v)
# Step 6: Dynamic Programming
dp_num = [0] * (N + 1)
dp_sum = [0] * (N + 1)
dp_num[0] = 1
for u in topo_order:
for v, l, a in edge_info[u]:
ways = dp_num[u] * a % MOD
sum_val = (dp_sum[u] * a + dp_num[u] * a % MOD * l) % MOD
dp_num[v] = (dp_num[v] + ways) % MOD
dp_sum[v] = (dp_sum[v] + sum_val) % MOD
print(dp_sum[N] % MOD)
if __name__ == "__main__":
main()
lam6er