[CSU 1804 有向无环图] DP+拓扑排序
题目链接:[CSU 1804 有向无环图]
题目描述:Bobo 有一个
n
个点,
为了方便,点用
∑i=1n∑j=1ncount(i,j)∗ai∗bj
除以
(109+7)
的余数。
其中, ai , bj 是给定的数列。
解题思路:这个题目想清楚了真的是一个大水题。但是还是很有灵活性的。可惜省赛的时候脑子不好使。
细细观察上面的式子,对于图中每个点(假设该点为 t ),设为
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 5;
const int MOD = 1e9 + 7;
struct Edge {
int v, next;
Edge() {}
Edge(int v, int next) : v(v), next(next) {}
} edges[MAXN];
int N, M;
int head[MAXN], ESZ, IN[MAXN];
LL A[MAXN], B[MAXN], cnt[MAXN];
queue<int> Q;
void init() {
ESZ = 0;
memset(head, -1, sizeof(head));
memset(IN, 0, sizeof(IN));
memset(cnt, 0, sizeof(cnt));
}
void add_edge(int u, int v) {
edges[ESZ] = Edge(v, head[u]);
head[u] = ESZ++;
}
void topu() {
int u, v;
while(!Q.empty()) Q.pop();
for (u = 1; u <= N; u++) {
if(!IN[u]) Q.push(u);
}
while(!Q.empty()) {
u = Q.front();
Q.pop();
for (int i = head[u]; ~i; i = edges[i].next) {
v = edges[i].v;
cnt[v] = (cnt[v] + cnt[u] + A[u]) % MOD;
IN[v] --;
if(!IN[v]) Q.push(v);
}
}
}
int main() {
// freopen("input.txt", "r", stdin);
int u, v;
LL ans;
while(~scanf("%d %d", &N, &M)) {
init();
for(int i = 1; i <= N; i++) {
scanf("%lld %lld", &A[i], &B[i]);
}
for(int i = 1; i <= M; i++) {
scanf("%d %d", &u, &v);
add_edge(u, v);
IN[v] ++;
}
topu();
ans = 0;
for (int i = 1; i <= N; i++) {
ans = (ans + cnt[i] * B[i] % MOD) % MOD;
}
printf("%lld\n", ans);
}
return 0;
}