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 }
当然也可以直接记忆化搜索 这样就可以确保拓扑序
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 }

浙公网安备 33010602011771号