164. 可达性统计

题目链接:https://www.acwing.com/problem/content/166/

思路: 拓扑序后 倒序来 用bitset 求并集, 对每个dp[i]  连出去的边 dp[v]求并集, 所以拓扑序后 求出dp[v] 就可以更新dp[i]

bitset 时间复杂度 二进制长度/32  时间复杂度 n/32*m

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3e4+10;
 4 const int mod=1e8;
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define pb push_back
 8 #define pi pair<int,int>
 9 #define fi first
10 #define sc second
11 
12 bitset<maxn>dp[maxn];
13 vector<int>E[maxn];
14 int ans[maxn];
15 int ru[maxn];
16 
17 
18 int main()
19 {
20     ios::sync_with_stdio(0);
21     cin.tie(0);
22     int n,m;
23     cin>>n>>m;
24     while(m--)
25     {
26         int x,y;
27         cin>>x>>y;
28         E[x].pb(y);
29         ru[y]++;
30     }
31     queue<int>q;
32     for(int i=1;i<=n;i++)
33     {
34         if(!ru[i]) q.push(i);
35     }
36 
37     int tot=0;
38     while(!q.empty())
39     {
40         int u=q.front();
41         ans[++tot]=u;
42         q.pop();
43         for(auto &v:E[u])
44         {
45             ru[v]--;
46             if(!ru[v]) q.push(v);
47         }
48     }
49 
50     for(int i=n;i>=1;i--)
51     {
52         int u=ans[i];
53         dp[u][u]=1;
54         for(auto &v:E[u])
55         {
56             dp[u]|=dp[v];
57         }
58     }
59     for(int i=1;i<=n;i++) cout<<dp[i].count()<<'\n';
60 
61 }
View Code

 

当然也可以直接记忆化搜索 这样就可以确保拓扑序

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3e4+10;
 4 const int mod=1e9+7;
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define pb push_back
 8 #define pi pair<int,int>
 9 #define fi first
10 #define sc second
11 
12 bitset<maxn>dp[maxn];
13 vector<int>E[maxn];
14 int st[maxn];
15 
16 
17 bitset<maxn> dfs(int u)
18 {
19     if(st[u]) return dp[u];
20     st[u]=1;
21     dp[u][u]=1;
22     for(auto &v:E[u])
23     {
24         dp[u]|=dfs(v);
25     }
26     return dp[u];
27 }
28 
29 
30 int main()
31 {
32     ios::sync_with_stdio(0);
33     cin.tie(0);
34     int n,m;
35     cin>>n>>m;
36     while(m--)
37     {
38         int x,y;
39         cin>>x>>y;
40         E[x].pb(y);
41     }
42     for(int i=1;i<=n;i++) cout<<dfs(i).count()<<'\n';
43 
44 
45 
46 }
View Code

 

posted @ 2021-03-25 22:19  canwinfor  阅读(64)  评论(0)    收藏  举报