[Nowcoder] 有向无环图 | 拓扑排序简单应用

Posted PushyTao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Nowcoder] 有向无环图 | 拓扑排序简单应用相关的知识,希望对你有一定的参考价值。

链接

题目描述

Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始、点 v 结束的路径)。
为了方便,点用 1 , 2 , … , n 1, 2, \\dots, n 1,2,,n编号。
c o u n t ( x , y ) \\mathrm{count}(x, y) count(x,y) 表示点 x 到点 y 不同的路径数量(规定 c o u n t ( x , x ) = 0 \\mathrm{count}(x, x) = 0 count(x,x)=0,Bobo 想知道
∑ i = 1 n ∑ j = 1 n c o u n t ( i , j ) ⋅ a i ⋅ b j \\sum_{i = 1}^n\\sum_{j = 1}^n \\mathrm{count}(i, j) \\cdot a_i \\cdot b_j i=1nj=1ncount(i,j)aibj
除以 ( 1 0 9 + 7 ) (10^9+7) (109+7) 的余数。
其中, a i , b j a_i, b_j ai,bj是给定的数列。

输入描述:

输入包含不超过 15 组数据。
每组数据的第一行包含两个整数 n, m ( 1 ≤ n , m ≤ 1 0 5 1 \\leq n, m \\leq 10^5 1n,m105)
接下来 n 行的第 i 行包含两个整数 a i , b i a_i, b_i ai,bi
( 0 ≤ a i , b i ≤ 1 0 9 (0 \\leq a_i, b_i \\leq 10^9 (0ai,bi109 ).
最后 m 行的第 i 行包含两个整数 u i , v i u_i, v_i ui,vi ,代表一条从点 u i u_i ui v i v_i vi的边 ( 1 ≤ u i , v i ≤ n ) (1 \\leq u_i, v_i \\leq n) (1ui,vin)
输出描述:
对于每组数据,输出一个整数表示要求的值。
示例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图,重要的是不存在环,所以说这道题我们可以通过拓扑排序来操作,在拓扑排序的过程中,先将队列里将要 p o p ( ) pop() pop()的元素 u u u加上 a [ u ] a[u] a[u],然后再从遍历所连边的时候,考虑贡献变化,然后用 r e s res res记录

#define Clear(x,val) memset(x,val,sizeof x)
struct node {
	int u,v,nex;
}e[maxn];
int n,m;
int cnt,head[maxn];
ll a[maxn],b[maxn];
int deg[maxn];
ll ans[maxn];
void init() {
	cnt = 0;
	Clear(head,-1);
	Clear(ans,0);
	Clear(deg,0);
}
void add(int u,int v){
	e[cnt].u = u;
	e[cnt].v = v;
	e[cnt].nex = head[u];
	head[u] = cnt ++;
}
ll res;
void topoSort(){
	queue<int> que;
	for(int i=1;i<=n;i++){
		if(deg[i] == 0) que.push(i);
	}
	while(que.size()){
		int u = que.front();
		que.pop();
		ans[u] = (ans[u] + a[u]) % mod;
		for(int i = head[u];~i;i = e[i].nex){
			int to = e[i].v;
			ans[to] = (ans[to] + ans[u]) % mod;
			res += ans[u] * b[to];
			res %= mod;
			-- deg[to];
			if(deg[to] == 0) que.push(to);
		}
	}
}
int main() {
	while(cin >> n >> m) {
		init();
		for(int i = 1;i <= n;i ++){
			a[i] = read,b[i] = read;
		}
		for(int i = 1;i <= m;i ++){
			int u = read,v = read;
			add(u,v);
			deg[v] ++;
		}
		res = 0;
		topoSort();
		cout << res << endl;
	}
	return 0;
}
/**


**/

以上是关于[Nowcoder] 有向无环图 | 拓扑排序简单应用的主要内容,如果未能解决你的问题,请参考以下文章

一个有向无环图的拓扑排序序列是否唯一的

有向无环图

一个有向无环图的拓扑排序序列是唯一的么

使用 拓扑排序进行有向无环图 任务关系拆解,实现任务编排

CSU 1804: 有向无环图(拓扑排序)

CSU 1804: 有向无环图 拓扑排序 图论