2016年湖南省第十二届大学生计算机程序设计竞赛:B—有向无环图
2017-05-10 23:47
453 查看
题目链接:传送门
Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始、点 v 结束的路径)。
为了方便,点用 1,2,…,n 编号。 设 count(x,y) 表示点 x 到点 y 不同的路径数量(规定 count(x,x)=0),Bobo 想知道
除以 (109+7) 的余数。
其中,ai,bj 是给定的数列。
输入包含不超过 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)。
对于每组数据,输出一个整数表示要求的值。
解题思路:拓扑排序+dp
一开始想用拓扑排序求出任意两点间的路径数目,然后暴力求出结果,但首先数组开不了这么大,其次0(n^2)肯定超时。后来看了题解,先求出count(i,j)*bj的值,用dp[i]保存(表示点i到其他所有点的路径数乘bj),这个可以在拓扑排序中求出,若从点i到点j,则有dp[i]+=dp[j]+b[j],得逆向求解,我们可以选择反向建边。最后ans=ai*dp[i]。
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
解题思路:拓扑排序+dp
一开始想用拓扑排序求出任意两点间的路径数目,然后暴力求出结果,但首先数组开不了这么大,其次0(n^2)肯定超时。后来看了题解,先求出count(i,j)*bj的值,用dp[i]保存(表示点i到其他所有点的路径数乘bj),这个可以在拓扑排序中求出,若从点i到点j,则有dp[i]+=dp[j]+b[j],得逆向求解,我们可以选择反向建边。最后ans=ai*dp[i]。
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <queue> #include <set> #include <string> #include <stack> #include <algorithm> using namespace std; typedef unsigned long long ull; const int N = 100010; const int M = 20; const int mod = 1e9+7; const int INF = 99999999; ull a ,b ,Indeg ,dp ,Ecnt; struct Edge { int node; Edge*next; }m_edge ; Edge*head ; void mkEdge( int a , int b ) { ++Indeg[b]; m_edge[Ecnt].node = b; m_edge[Ecnt].next = head[a]; head[a] = m_edge+Ecnt++; } void init() { Ecnt = 0; fill( head , head+N , (Edge*)0 ); fill( Indeg , Indeg+N , 0 ); fill( dp , dp+N , 0 ); } void topoSort( int n ) { queue<int>point; for( int i = 1 ; i <= n ; ++i ){ if( 0 == Indeg[i] ) point.push( i ); } while( !point.empty() ){ int t = point.front(); point.pop(); for( Edge*p = head[t] ; p ; p = p->next ){ int s = p->node; dp[s] = ((dp[t]+b[t])%mod+dp[s])%mod; --Indeg[s]; if( 0 == Indeg[s] ) point.push(s); } } } int main() { int n,m,u,v; while( ~scanf("%d%d",&n,&m) ){ init(); for( int i = 1 ; i <= n ; ++i ){ scanf("%d%d",&a[i],&b[i]); } for( int i = 0 ; i < m ; ++i ){ scanf("%d%d",&u,&v); mkEdge( v , u ); } topoSort( n ); ull ans = 0; for( int i = 1 ; i <= n ; ++i ){ ans = ((a[i]*dp[i])%mod+ans)%mod; } printf("%lld\n",ans); } return 0; }
相关文章推荐
- 2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)
- 2016年湖南省第十二届大学生计算机程序设计竞赛:G—parathesis
- 2016年湖南省第十二届大学生计算机程序设计竞赛 - G CSU 1809 Parenthesis (线段树)
- 2016年湖南省第十二届大学生计算机程序设计竞赛 A. 2016(数学)
- 2016年湖南省第十二届大学生计算机程序设计竞赛(重现)
- csu 2016年湖南省第十二届大学生计算机程序设计竞赛Problem A 2016
- CSU 1809 Parenthesis (线段树)【2016年湖南省第十二届大学生计算机程序设计竞赛 - G】
- 2016年湖南省第十二届大学生计算机程序设计竞赛:A—2016
- 2016年湖南省第十二届大学生计算机程序设计竞赛
- 2016年湖南省第十二届大学生计算机程序设计竞赛:F—地铁
- 2016年湖南省第十二届大学生计算机程序设计竞赛(重现) A 2016
- 2016年湖南省第十二届大学生计算机程序设计竞赛 A 2016(数学)
- 2016年湖南省第十二届大学生计算机程序设计竞赛 J 三角形和矩形(计算几何)
- CSU1810(2016年湖南省第十二届大学生计算机程序设计竞赛 - H)
- 2016年湖南省第十二届大学生计算机程序设计竞赛
- CSU 1803 2016 (数学)【2016年湖南省第十二届大学生计算机程序设计竞赛 - A】
- 2016年湖南省第十二届大学生计算机程序设计竞赛 解题报告
- 【数学】CSU 1810 Reverse (2016湖南省第十二届大学生计算机程序设计竞赛)
- 【最短路】【数学】CSU 1806 Toll (2016湖南省第十二届大学生计算机程序设计竞赛)
- 湖南省第十二届大学生计算机程序设计竞赛 problem A 2016