[Nowcoder] 有向无环图 | 拓扑排序简单应用
题目描述
Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始、点 v 结束的路径)。
为了方便,点用
1
,
2
,
…
,
n
1, 2, \dots, n
1,2,…,n编号。
设
c
o
u
n
t
(
x
,
y
)
\mathrm{count}(x, y)
count(x,y) 表示点 x 到点 y 不同的路径数量(规定
c
o
u
n
t
(
x
,
x
)
=
0
\mathrm{count}(x, x) = 0
count(x,x)=0,Bobo 想知道
∑
i
=
1
n
∑
j
=
1
n
c
o
u
n
t
(
i
,
j
)
⋅
a
i
⋅
b
j
\sum_{i = 1}^n\sum_{j = 1}^n \mathrm{count}(i, j) \cdot a_i \cdot b_j
∑i=1n∑j=1ncount(i,j)⋅ai⋅bj
除以
(
1
0
9
+
7
)
(10^9+7)
(109+7) 的余数。
其中,
a
i
,
b
j
a_i, b_j
ai,bj是给定的数列。
输入描述:
输入包含不超过 15 组数据。
每组数据的第一行包含两个整数 n, m (
1
≤
n
,
m
≤
1
0
5
1 \leq n, m \leq 10^5
1≤n,m≤105)
接下来 n 行的第 i 行包含两个整数
a
i
,
b
i
a_i, b_i
ai,bi
(
0
≤
a
i
,
b
i
≤
1
0
9
(0 \leq a_i, b_i \leq 10^9
(0≤ai,bi≤109 ).
最后 m 行的第 i 行包含两个整数
u
i
,
v
i
u_i, v_i
ui,vi ,代表一条从点
u
i
u_i
ui到
v
i
v_i
vi的边
(
1
≤
u
i
,
v
i
≤
n
)
(1 \leq u_i, v_i \leq n)
(1≤ui,vi≤n)
输出描述:
对于每组数据,输出一个整数表示要求的值。
示例1
输入
3 3
1 1
1 1
1 1
1 2
1 3
2 3
输出
4
示例2
输入
2 2
1 0
0 2
1 2
1 2
输出
4
示例3
输入
2 1
500000000 0
0 500000000
1 2
输出
250000014
因为是DAG图,重要的是不存在环,所以说这道题我们可以通过拓扑排序来操作,在拓扑排序的过程中,先将队列里将要 p o p ( ) pop() pop()的元素 u u u加上 a [ u ] a[u] a[u],然后再从遍历所连边的时候,考虑贡献变化,然后用 r e s res res记录
#define Clear(x,val) memset(x,val,sizeof x)
struct node {
int u,v,nex;
}e[maxn];
int n,m;
int cnt,head[maxn];
ll a[maxn],b[maxn];
int deg[maxn];
ll ans[maxn];
void init() {
cnt = 0;
Clear(head,-1);
Clear(ans,0);
Clear(deg,0);
}
void add(int u,int v){
e[cnt].u = u;
e[cnt].v = v;
e[cnt].nex = head[u];
head[u] = cnt ++;
}
ll res;
void topoSort(){
queue<int> que;
for(int i=1;i<=n;i++){
if(deg[i] == 0) que.push(i);
}
while(que.size()){
int u = que.front();
que.pop();
ans[u] = (ans[u] + a[u]) % mod;
for(int i = head[u];~i;i = e[i].nex){
int to = e[i].v;
ans[to] = (ans[to] + ans[u]) % mod;
res += ans[u] * b[to];
res %= mod;
-- deg[to];
if(deg[to] == 0) que.push(to);
}
}
}
int main() {
while(cin >> n >> m) {
init();
for(int i = 1;i <= n;i ++){
a[i] = read,b[i] = read;
}
for(int i = 1;i <= m;i ++){
int u = read,v = read;
add(u,v);
deg[v] ++;
}
res = 0;
topoSort();
cout << res << endl;
}
return 0;
}
/**
**/