Description
Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始、点 v 结束的路径)。
为了方便,点用 1,2,…,n 编号。 设 count(x,y) 表示点 x 到点 y 不同的路径数量(规定 count(x,x)=0),Bobo 想知道

除以 (10
9+7) 的余数。
其中,a
i,b
j 是给定的数列。
Input
输入包含不超过 15 组数据。
每组数据的第一行包含两个整数 n,m (1≤n,m≤10
5).
接下来 n 行的第 i 行包含两个整数 a
i,b
i (0≤a
i,b
i≤10
9).
最后 m 行的第 i 行包含两个整数 u
i,v
i,代表一条从点 u
i 到 v
i 的边 (1≤u
i,v
i≤n)。
Output
对于每组数据,输出一个整数表示要求的值。
思路:
表达式的本质是求出所有点对(i,j)对应的路径数乘上点i,j上的量。
我们考虑固定i,由于是有向无环图,所有的j必然是在i之后出现;而i必然是通过i的某个后继到达j。所以如果我们已经知道了i的后继vk对应的sk=count(v,j)*bj,那么只要累加sk后*ai即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int mo=1e9+7;
const int maxn=1e5+10;
int head[maxn],e[2*maxn],nex[2*maxn];
int a[maxn],b[maxn],vis[maxn],f[maxn];
int ans,tot;
void add_edge(int u,int v){
e[tot]=v;nex[tot]=head[u];head[u]=tot++;
}
void dfs(int u){
int v,i;
f[u]=0;vis[u]=1;
if (head[u]==-1) {
f[u]=b[u];
return;
}
for (i=head[u];i!=-1;i=nex[i]){
v=e[i];
if (!vis[v]) dfs(v);
f[u]=(f[u]+f[v])%mo;
}
ans=(ans+(long long)f[u]*a[u]%mo)%mo;
f[u]=(f[u]+b[u])%mo;
}
int main()
{
int i,n,m,u,v;
while (scanf("%d %d",&n,&m)!=-1){
for (i=1;i<=n;i++) head[i]=-1;
tot=0;
for (i=1;i<=n;i++){
scanf("%d %d",&a[i],&b[i]);
}
for (i=1;i<=m;i++){
scanf("%d %d",&u,&v);
add_edge(u,v);
}
memset(vis,0,sizeof(vis));
ans=0;
for (i=1;i<=n;i++){
if (!vis[i]) dfs(i);
}
printf("%d\n",ans);
}
return 0;
}
/**************************************************************
Problem: 1804
User: xushu
Language: C++
Result: Accepted
Time:480 ms
Memory:5216 kb
****************************************************************/