搜索-树与图的遍历 【可达性统计】 (拓扑,bitset)

树与图的遍历

拓扑排序(练习题)-CSDN博客

习题:可达性统计

思路

题目涉及到了bitset,状态压缩,可以看下这个 bitset 用法函数,状态压缩,练习题-CSDN博客

这里用了两种方法,如下:

  1. 运用记忆化,不断深搜所能达的点,并
    进行|运算

    用set存放子节点,函数返回bitset类型

  2. 运用无后继–拓扑排序,因为子节点影响父节点,所以倒着来

    出度为0,推入q

    父节点|=子节点

代码

记忆化搜索+dfs+dp

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N=3e4+10;
bool vis[N];//标记访问过的,实现记忆化
bitset<N> dp[N];//存储能遍历到该点的状态
set<int> sons[N];
bitset<N> dfs(int u)
{
     if(vis[u]) return dp[u];
     vis[u]=true;
     dp[u].set(u);//u处置为1
     for(auto &it:sons[u])
     dp[u] |=dfs(it);//dfs里是小括号
     return dp[u];
}
signed main()
{
	IOS
	int n,m,u,v;
	cin>>n>>m;
	while(m--)
	{
	    cin>>u>>v;
	    sons[u].insert(v);
	}
	for(int i=1;i<=n;i++)
	cout<<dfs(i).count()<<'\n';
}

拓扑排序+bfs

/*
 * Project: 搜索,拓扑,状态压缩
 * File Created: 7.27  2024
 * Author: feishi
 * Problem:Acwing 164. 可达性统计
 */

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
queue <int> q;
const int N=3e4+10;
vector<int> ind[N];//存入度点
bitset<N> dp[N];
int chu[N];//记录出度数量,因为求得的是可达数量,倒序
signed main()
{
	IOS
	int n,m,u,v;
	cin>>n>>m;
	while(m--)
	{
	    cin>>u>>v;
	    ind[v].push_back(u);
	    chu[u]++;
	}
	for(int i=1;i<=n;i++)
	{
	    if(chu[i]==0)
	    {
	        q.push(i);
	        dp[i].set(i);
	    }
	}
	 
	while(!q.empty())
	{
	    int io=q.front();
	    q.pop();
	    for(auto &it:ind[io])
	    {
	        chu[it]--;
	        dp[it]|=dp[io];//io|他的出度
	        if(chu[it]==0)
	        {
	            dp[it].set(it);
	             q.push(it);
	        }
	        
	    }
	}
	for(int i=1;i<=n;i++)
	cout<<dp[i].count()<<'\n';
}

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值