题干:
链接:https://ac.nowcoder.com/acm/contest/1112/B
来源:牛客网
Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始、点 v 结束的路径)。
为了方便,点用 1,2,…,n 编号。设
c
o
u
n
t
(
x
,
y
)
c
o
u
n
t
(
x
,
y
)
\mathrm{count}(x, y)count(x,y)
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}count(i,j)⋅a i⋅b j
∑i=1n∑j=1ncount(i,j)⋅ai⋅bj,除以 (
1
0
9
10^9
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
到
v
i
u_i到 v_i
ui到vi的边 (
1
≤
u
i
,
v
i
≤
n
1 \leq u_i, v_i \leq n
1≤ui,vi≤n)。
对于每组数据,输出一个整数表示要求的值。
输入:3 3
1 1
1 1
1 1
1 2
1 3
2 3
输出:4
输入:2 2
1 0
0 2
1 2
1 2
输出:4
输入:2 1
500000000 0
0 500000000
1 2
输出:250000014
思路:
根据
a
∗
b
+
c
∗
b
=
(
a
+
c
)
∗
b
a*b+c*b=(a+c)*b
a∗b+c∗b=(a+c)∗b这一性质,如果存在类似x->y->z这种路,
a
[
x
]
∗
b
[
y
]
+
a
[
x
]
b
[
z
]
+
a
[
y
]
b
[
z
]
a[x]*b[y]+a[x]b[z]+a[y]b[z]
a[x]∗b[y]+a[x]b[z]+a[y]b[z],可以写成
a
[
x
]
∗
b
[
y
]
+
(
a
[
x
]
+
a
[
y
]
)
∗
b
[
z
]
a[x]*b[y]+(a[x]+a[y])*b[z]
a[x]∗b[y]+(a[x]+a[y])∗b[z]即x->z这条路可以在求y->z时求出。
这样我们把起点(即入度为0的点)入队开始搜索,找到他的所有出度,并使出度点的a[v]加上入度的点a[u],然后如果当前出度点的入度为0了,就把它也入队。
因为每次只搜一段,所有不同的路径都会被搜到。
然后为了防止意外用了快速乘。
#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
ll a[100010],b[100010],in[100010];
vector<int> v[100010];
queue<int> q;
ll ksc(ll x,ll y){
ll res=0;
while(y){
if(y&1)
res=(res+x)%mod;
x=(x<<1)%mod;
y>>=1;
}
return res;
}
int main()
{
int n,m,x,y;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=0;i<=n;i++)
v[i].clear();
memset(in,0,sizeof(in));
long long ans=0;
for(int i=1;i<=n;i++){
scanf("%lld%lld",&a[i],&b[i]);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
v[x].push_back(y);
in[y]++;
}
for(int i=1;i<=n;i++){
if(!in[i])
q.push(i);
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<v[u].size();i++){
int v1=v[u][i];
ans=(ans+ksc(a[u],b[v1]))%mod;
a[v1]=(a[v1]+a[u])%mod;
in[v1]--;
if(!in[v1]){
q.push(v1);
}
}
}
printf("%lld\n",ans);
}
return 0;
}