湖南省第十二届大学生计算机程序设计竞赛 B 有向无环图 拓扑DP

1804: 有向无环图

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 187  Solved: 80
[Submit][Status][Web Board]

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

对于每组数据,输出一个整数表示要求的值。

Sample Input

3 3
1 1
1 1
1 1
1 2
1 3
2 3
2 2
1 0
0 2
1 2
1 2
2 1
500000000 0
0 500000000
1 2

Sample Output

4
4
250000014

题解:

  quality:dp[u]表示从u出发能到达的所有v的count[v]*b[v]之和,那么u的一个后继v对dp[u]有dp[v]+b[v]的贡献,按照反向拓扑序dp

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair

typedef long long LL;
const long long INF = 1e18;
const double Pi = acos(-1.0);
const int N = 2e5+10, M = 1e6+11, mod = 1e9+7, inf = 5000;

int n,m;
LL a[N],b[N];
int d[N],t,head[N];
LL dp[N];

struct ss{int to,next;}e[N * 2];
void add(int u,int v) {e[t].to=v;e[t].next = head[u];head[u]=t++;}

int main() {
        while(scanf("%d%d",&n,&m)!=EOF) {
            for(int i = 1; i <= n; ++i)  scanf("%I64d%I64d",&a[i],&b[i]);
            memset(d,0,sizeof(d));t = 1;
            memset(head,0,sizeof(head));
            for(int i = 1; i <= m; ++i) {
                int u,v;
                scanf("%d%d",&u,&v);
                add(v,u);
                d[u] += 1;
            }
            memset(dp,0,sizeof(dp));
            queue<int  > q;
            for(int i = 1; i <= n; ++i) {
                if(d[i] == 0) {
                    q.push(i);
                }
            }
            while(!q.empty()) {
                int u = q.front();
                q.pop();
                for(int i = head[u]; i; i = e[i].next) {
                    int to = e[i].to;
                    dp[to] += (dp[u] + b[u]);
                    dp[to] %= mod;
                    d[to]--;
                    if(d[to] == 0) q.push(to);
                }
            }

            LL ans = 0;
            for(int i = 1; i <= n; ++i) {
              //  cout<<dp[i]<<endl;
                ans += ((a[i] * dp[i])%mod);
                ans %= mod;
            }
            cout<<(ans+mod)% mod<<endl;
        }
    return 0;
}
原文地址:https://www.cnblogs.com/zxhl/p/5839606.html