【题解】牛客 有向无环图⭐⭐⭐ 【dp DFS】

牛客 有向无环图

【题解】牛客 有向无环图⭐⭐⭐ 【dp DFS】_第1张图片

Input

在这里插入图片描述

Output

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

Examples

示例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图, 对于所有入度为0的点即对应一个联通块, 然后Dfs搜一下
dp[i]表示从 i 点出发到所有点的所有路径对应 b[j] 之和, 包括其自身


#include
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const int INF = 1 << 30;
const int MAXN = 1e5+10;
const LL mod = 1e9+7;

LL dp[MAXN], a[MAXN], b[MAXN], in[MAXN], N, M;
vector<int> G[MAXN];
bool vis[MAXN];
void addEdge(int u, int v){G[u].push_back(v);}
int Dfs(int u){
    if(vis[u]) return dp[u];
    dp[u] = b[u], vis[u] = true;
    for(auto v : G[u]){
        Dfs(v);
        dp[u] = (dp[u]+dp[v])%mod;
    }
    return dp[u];
}
int main() {
    ios::sync_with_stdio(false);
    cin >> N >> M;
        int u, v;
        for(int i = 1; i <= N; ++i){
            cin >> a[i] >> b[i];
            vis[i] = false, in[i] = dp[i] = 0;
        }
        while(M--){
            cin >> u >> v;
            addEdge(u, v);
            ++in[v];
        }
        for(int i = 1; i <= N; ++i)
            if(in[i] == 0)
                Dfs(i);
        LL ans = 0;
        for(int i = 1; i <= N; ++i){
            ans = (ans+(a[i]*(dp[i]-b[i])%mod))%mod;
            ans = (ans % mod + mod) % mod;
        }
        cout << ans << endl;
    
    return 0;
}

你可能感兴趣的:(图论)