CSU 1804: 有向无环图

来源:互联网 发布:九九乘法表c语言编程 编辑:程序博客网 时间:2024/05/22 01:26

Description

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

Input

输入包含不超过 15 组数据。
每组数据的第一行包含两个整数 n,m (1≤n,m≤105).
接下来 n 行的第 i 行包含两个整数 ai,bi (0≤ai,bi≤109).
最后 m 行的第 i 行包含两个整数 ui,vi,代表一条从点 ui 到 vi 的边 (1≤ui,vi≤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****************************************************************/


0 0
原创粉丝点击