多久没写东西了啊。。。。
两道拓扑排序Liv.1的题。。。。方法是一样的~~
《拓扑排序·二》
题目:http://hihocoder.com/contest/hiho81/problem/1
一个电脑网路,单向边,如果存在边u->v,那么u的病毒会感染到v。
要点,不存在环!那么如果u的入度=0的话,那么u中的病毒数不会再变化。
想到拓扑排序。不断删去入度为0的点。每次删去节点u,如果存在u->v,那么病毒数
num[v] += num[u]。问题解决。
(用queue实现拓扑排序很方便~~)
代码:
1 #include<bits/stdc++.h>
2
3 using namespace std;
4 const int maxn = 100000 + 10;
5 const int mod = 142857;
6 int n, m, k;
7 int num[maxn], in[maxn];
8 vector<int> G[maxn];
9
10 int solve(){
11 queue<int> q;
12
13 int ans = 0;
14 for( int i = 1; i <= n; ++i ){
15 if(!in[i]){
16 //cout << "i: " << i << endl;
17 q.push(i);
18 }
19 }
20
21 while(!q.empty()){
22 int u = q.front(); q.pop();
23 ans = ( ans + num[u] )%mod;
24
25 for( int i = 0; i < G[u].size(); ++i ){
26 int v = G[u][i];
27 in[v]--; num[v] = (num[u] + num[v])%mod;
28 if(!in[v])
29 q.push(v);
30 }
31 }
32
33 return ans;
34 }
35
36 int main(){
37 scanf("%d%d%d", &n, &m, &k);
38
39 memset( num, 0, sizeof(num) );
40 int u, v;
41 for( int i = 0; i < k; ++i ){
42 scanf("%d", &u);
43 num[u]++;
44 }
45
46 memset( in, 0, sizeof(in) );
47 for( int i = 0; i < m; ++i ){
48 scanf("%d%d", &u, &v);
49 G[u].push_back(v); in[v]++;
50 }
51
52 int ans = solve();
53 printf("%d\n", ans);
54
55 return 0;
56 }