1804: 有向无环图
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 341 Solved: 152
[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 思路:拓扑排序+dp;按照拓扑将点权合并就可以了。
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<iostream> 5 #include<math.h> 6 #include<queue> 7 #include<vector> 8 using namespace std; 9 typedef long long LL; 10 LL mod = 1e9+7; 11 LL dp[100005]; 12 int cnt[100005]; 13 LL a[100005]; 14 LL b[100005]; 15 vector<int>vec[100005]; 16 queue<int>que; 17 int main(void) 18 { 19 int n,m; 20 while(scanf("%d %d",&n,&m)!=EOF) 21 { 22 int i,j;LL ask ; 23 while(!que.empty()) 24 que.pop(); 25 for(i = 0; i < 100005; i++) 26 vec[i].clear(); 27 memset(cnt,0,sizeof(cnt)); 28 memset(dp,0,sizeof(dp)); 29 for(i = 1; i <= n; i++) 30 { 31 scanf("%lld %lld",&a[i],&b[i]); 32 } 33 while(m--) 34 { 35 int x,y; 36 scanf("%d %d",&x,&y); 37 cnt[y]++; 38 vec[x].push_back(y); 39 } 40 for(i = 1; i <= n; i++) 41 { 42 if(cnt[i] == 0) 43 { 44 que.push(i); 45 } 46 } 47 while(!que.empty()) 48 { 49 int x = que.front(); 50 que.pop(); 51 for(i = 0;i < vec[x].size();i++) 52 { 53 int y = vec[x][i]; 54 cnt[y] --; 55 if(cnt[y] == 0) 56 que.push(y); 57 dp[y] = dp[y]+a[x]*b[y]%mod; 58 dp[y]%=mod; 59 a[y] = a[y] + a[x]; 60 a[y]%=mod; 61 ask = dp[y]; 62 } 63 }ask = 0; 64 for(i = 1;i <= n;i++) 65 { 66 ask = ask + dp[i]; 67 ask %= mod; 68 } 69 printf("%lld\n",ask); 70 } 71 return 0; 72 }
时间: 2024-10-08 22:04:14