📅  最后修改于: 2023-12-03 15:28:45.714000             🧑  作者: Mango
本题要求实现一个函数,具体内容和要求如下:
现在有一个含有n个节点的有向图G,每个节点有一个权重值,权重值为正整数。现在有一个整数x,请你编写一个函数 numberOfPaths(G, x)
,需返回以下两个必要信息的元组:
由于答案可能相当大,这里请你输出对1000000007取模的结果。
def numberOfPaths(G: List[List[int]], x: int) -> Tuple[int, int]:
参数 | 说明 ----|---- G | 给定的有向图,G[i]表示从节点i出发可以到达的节点集合,节点权重值已经存储在了一个元组weightList中,节点的序号从1开始编号。 x | 给定的整数x,表示需要统计的中点或起点
说明 | 类型 -----|----- S_x | int S_m | int
下面给出参考代码示例,其中weightList为节点权重列表。
from typing import List, Tuple
def numberOfPaths(G: List[List[int]], x: int) -> Tuple[int, int]:
mod = 1000000007
n = len(G)
weightList = [0] * (n+1) #节点权重列表
Sroot = [0] * (n+1)
Sx = [0] * (n+1)
Stot = 0
totChild = [1]*(n+1)
f = [0]*(n+1)
g = [0]*(n+1)
vis = [False]*(n+1)
# 获取节点权重列表
for i in range(1, n+1):
weightList[i] = input()
def dfs(u):
Sx[u] = Sroot[u]
for v in G[u]:
if v == f[u] or vis[v]:
continue
f[v] = u
dfs(v)
totChild[u] += totChild[v]
Sx[u] = (Sx[u] + g[u]*f[v]%mod + f[u]*g[v]%mod + f[u]*f[v]%mod*totChild[v]%mod)%mod
g[u] = (g[u] + g[v] + f[v]*totChild[v]%mod)%mod
vis[u] = True
def dfs2(u):
nonlocal Stot
Sroot[u] = 1
Stot = (Stot + weightList[u])%mod
for v in G[u]:
if vis[v]:
continue
dfs2(v)
Sroot[u] = (Sroot[u] + Sroot[v])%mod
dfs2(x)
vis[x] = True
for v in G[x]:
f[v] = x
dfs(v)
totChild[x] += totChild[v]
S_x = (S_x + g[x]*f[v]%mod + f[x]*g[v]%mod + f[x]*f[v]%mod*totChild[v]%mod)%mod
S_m = (Stot*S_x*S_x%mod-2*Sx[x]*S_x%mod*S_x%mod)%mod
return (S_x, S_m)
首先,定义节点总数n,以及一个长度为n+1的Sroot、Sx、weightList数组,还有对应长度的totChild、f、g、vis数组。
然后,定义dfs函数,其实现可以考虑右图中的递归过程。
def dfs(u):
Sx[u] = Sroot[u]
for v in G[u]:
if v == f[u] or vis[v]:
continue
f[v] = u
dfs(v)
totChild[u] += totChild[v]
Sx[u] = (Sx[u] + g[u]*f[v]%mod + f[u]*g[v]%mod + f[u]*f[v]%mod*totChild[v]%mod)%mod
g[u] = (g[u] + g[v] + f[v]*totChild[v]%mod)%mod
vis[u] = True
其中,Sx[u]表示抵达u节点经过x这个中转点的路径数量,Sroot[u]表示u节点的子孙节点到u节点的最短路径数量。
在dfs过程中,对于从u出发可以到达的每个节点v,统计从v到u节点的路径数量:
在每个节点遍历完成后,标记其已遍历过,更新Sx、Sroot数组。
例如,对于Sx[u],可以通过下列方式得到:
同时,编号为x的节点自身也单独处理,从而在dfs函数的操作中避免了x被多次计数的情况。
最后,计算S_x、S_m。
上述算法中dfs和dfs2的时间复杂度都为O(N),根据题目中N≤20000,可以考虑直接使用该算法。
因此,该算法的时间复杂度为O(N),空间复杂度为O(N)。