两道拓扑排序的问题

多久没写东西了啊。。。。

两道拓扑排序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 }
View Code

 

《hiho一下 第八十一周》

题目:http://hihocoder.com/contest/hiho81/problem/1

方法相同,建图稍微难点。。。

代码:

 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;  7 vector<int> in[maxn];  8 int s[maxn], ru[maxn], num[maxn];  9 vector<int> e[maxn], G[maxn]; 10 11 void init(){ 12 for( int i = 0; i < maxn; ++i ) 13 in[i].clear(), e[i].clear(), G[i].clear(); 14 memset( s, 0, sizeof(s) ); 15 memset( ru, 0, sizeof(ru) ); 16 memset( num, 0, sizeof(num) ); 17 } 18 19 void solve(){ 20 queue<int> q; 21 for( int i = 0; i <= n; ++i ){ 22 if(!ru[i]) 23  q.push(i); 24  } 25 26 while(!q.empty()){ 27 int u = q.front(); q.pop(); 28 for( int i = 0; i < G[u].size(); ++i ){ 29 int v = G[u][i]; 30 ru[v]--, num[v] = (num[v] + num[u])%mod; 31 if(!ru[v]) 32  q.push(v); 33  } 34  } 35 } 36 37 void print(){ 38 printf("%d", num[1]); 39 for( int i = 2; i <= n; ++i ){ 40 printf(" %d", num[i]); 41  } 42 printf("\n"); 43 } 44 45 int main(){ 46 //freopen("1.in", "r", stdin); 47 int T; 48 scanf("%d", &T); 49 50 while(T--){ 51  init(); 52 scanf("%d%d", &n, &m); 53 54 int u, v, k; 55 s[0] = -1, num[0] = 1; 56 for( int i = 0; i < m; ++i ){ 57 scanf("%d", &u); 58 e[0].push_back(u); 59  } 60 61 for( int i = 1; i <= n; ++i ){ 62 scanf("%d%d", &u, &k); 63 s[i] = u; in[u].push_back(i); 64 for( int j = 0; j < k; ++j ){ 65 scanf("%d", &u); 66  e[i].push_back(u); 67  } 68  } 69 70 //build graph 71 for( int i = 0; i <= n; ++i ){ 72 for( int j = 0; j < e[i].size(); ++j ){ 73 int sg = e[i][j]; 74 for( int p = 0; p < in[sg].size(); ++p ){ 75 int v = in[sg][p]; ru[v]++; 76  G[i].push_back(v); 77 

转载于:https://www.cnblogs.com/zhazhalovecoding/p/5150561.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值