当前位置: 首页 > wzjs >正文

电影网站建设哪家便宜麓谷网站建设

电影网站建设哪家便宜,麓谷网站建设,东莞 包装制品 东莞网站建设,前端seo主要优化哪些我们还能不能再见面 我向上天苦苦求了几千年 愿意用几世换我们一世情缘 希望可以感动上天 可达性统计(拓扑排序模板,bitset) 目录可达性统计(拓扑排序模板,bitset)拓扑排序(Kahn 算法&#xff0…

我们还能不能再见面
我向上天苦苦求了几千年
愿意用几世换我们一世情缘
希望可以感动上天

可达性统计(拓扑排序模板,bitset)

目录

  • 可达性统计(拓扑排序模板,bitset)
    • 拓扑排序(Kahn 算法)
    • 代码分析

164. 可达性统计 - AcWing题库

给你一张有向无环图,统计每个点能到达几个点;

一开始想用dfs遍历图查找每个点能通向那些点,但是超时了,所以就就需要用到其他的算法去优化时间了;

紧接着就想到了动态规划,先把每个点能到达的点数存起了,这样上面的点的到达数就是后面的点的到达数的和了!但是现实很骨感,每个点都有可能被多个点到达,多以直接累加的话就会重复计数导致答案错误;

所以我们就需要去重。因此我们也不难得出,每个点能到达的点集就是子节点能到达的点集的并集再加上自己!元就是

f(x)={x}∪(⋃存在有向边(x,y)f(y))f(x)=\{x\}\cup\left(\bigcup_{\text{存在有向边}(x,y)}f(y)\right)f(x)={x}(存在有向边(x,y)f(y))

如果直接用数组去模拟每次求并集的操作每次都要遍历一遍,太慢了。数和数之间的到达情况只分为两种(能到或不能到)所以不难想到利用二进制和位运算去表示,这样每次求并集就是位运算里面的|(按位或)的操作,时间大幅减少!可以利用bitset轻松实现二进制的枚举;

bitset的具体介绍可以看维基,里面很清楚,就是一个二进制的工具;


拓扑排序(Kahn 算法)

分析完题目,思路已经清晰;但是我们应该从那个点入手作为最基础的集合呢?

不难想到,肯定是最后面的点,也就是没有链接其他点的点,这样他的点集就只有他自己,可以作为dp的初始量!

所以这个就可以用到拓扑排序!

给定一张有向无环图,若一个由图中所有点构成的序列 AAA 满足:对于图中的每条边(x,y),x(x,y),x(x,y),xAAA中都出现在yyy之前,则称AAA是该有向无环图顶点的一个拓扑序。求解序列AAA的过程就称为拓扑排序。

拓扑排序过程的思想非常简单,我们只需要不断选择图中入度为 0 的节点 xxx,然后把xxx连向的点的入度减 1。我们可以结合广度优先遍历的框架来高效地实现这个过程:

下面介绍一下Kahn (卡恩) 算法 \text { Kahn (卡恩) 算法 } Kahn (卡恩算法 (利用数组建图时的操作)

p[x]p[x]p[x] 存点 xxx 的邻点。tptptp 存拓扑序列。rd[x]rd[x]rd[x] 存点 xxx 的入度。

算法的核心用队列维护一个入度为 0 的节点的集合。

  1. 初始化。队列 qqq 入压所有入度为 0 的点。
  2. 每次从 qqq 中取出一个点 xxx 放入数组 tptptp
  3. 然后将 xxx 的所有邻点删除。若将边 (x,y)(x, y)(x,y) 删除后,yyy 的入度变为 0,则将 yyy 压入 qqq 中。
  4. 不断重复 2.3 过程,直到队列 qqq 为空。
  5. tptptp 中的元素个数等于 nnn,则有拓扑序;否则,有环。
void topsort(){queue<int> q;for(int i=1;i<=n;i++)if(rd[i]==0)q.push(i);while(q.size()){int t=q.front();q.pop();tp.push_back(t);for(auto i:p[t]){if(--rd[i]==0)q.push(i);}}
}

最后生成的tp数组中里面的点是无环的!所以通过tp数组的长度可以判断原数组中有无环的出现;

而且他的顺序是线性的!也就是如果两点间有通路,那么一定是前面的数指向后面的数!

这样我们就能按照从后往前去遍历拓扑数组,对状态进行累加了;


代码分析

解题思路与策略

该问题是在有向无环图(DAG)上计算每个节点可达的节点数量。核心思路是将拓扑排序与bitset位压缩技术结合,实现高效的可达性统计。

关键步骤

  1. 拓扑排序

    • 初始化队列,将所有入度为0的节点入队
    • 每次取出队首节点加入拓扑序列,并更新其后继节点的入度
    • 当后继节点入度降为0时将其入队
    • 最终得到拓扑排序的序列tp
  2. 逆序DP计算可达集合

    • 关键点:按拓扑序列的逆序处理节点(从后往前)

    • 初始化:当前节点可达自身dp[u][u]=1

    • 状态转移:对于每个节点u,将其所有后继节点的可达集合进行"或"操作:

      dp[u] |= dp[v] v是u的直接后继

    • 逆序处理保证:计算节点u时,其后继节点v都已被计算过

  3. 结果输出

    • 每个节点的dp值是一个bitset,其count()即为可达节点数

    • bitset的大小设为30005(题目数据范围n≤30000)

注意要点

  1. bitset大小设置

    bitset<30005> dp[N] 必须严格大于最大n值,且<>里面不能是变量

  2. 拓扑逆序处理

    for(int i=n-1;i>=0;i--){  // 逆序遍历拓扑序列int t=tp[i];          // 从后往前处理节点
    }
    
  3. 自环处理

    dp[t][t/] = 1 初始化:每个节点可达自身

整体代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
const int N=3e5+5;
int n,m;
vector <int> p[N],tp,rd(N);
bitset<30005> dp[N];
void topsort(){queue<int> q;for(int i=1;i<=n;i++)if(rd[i]==0)q.push(i);while(q.size()){int t=q.front();q.pop();tp.push_back(t);for(auto i:p[t]){if(--rd[i]==0)q.push(i);}}
}
void slove(){cin>>n>>m;for(int i=1;i<=m;i++){int x,y;cin>>x>>y;rd[y]++;p[x].push_back(y);}topsort();for(int i=n-1;i>=0;i--){int t=tp[i];dp[t][t]=1;for(auto j:p[t])dp[t]|=dp[j];}for(int i=1;i<=n;i++)cout<<dp[i].count()<<endl;
} 
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;//cin>>_;while(_--)slove();return 0;
}

http://www.dtcms.com/wzjs/597612.html

相关文章:

  • 企业网站策划方案模板网站开发系统规划
  • 17zwd一起做网站广州新塘微信商户平台登录入口
  • 建站公司郑州本溪网站开发
  • 个人模板网站昆山规划建设局网站
  • 襄阳网站建设价格wordpress双语
  • 网络公司网站设计维护合同广州外贸网站咨询
  • 如何在自己网站添加链接丹阳房价
  • 网站开发技术参数佛山企业网站建设技术
  • 微网站公司专业的开发网站建设
  • 推荐盐城网站开发营销智库网站
  • 什么企业做网站无法打开网页如何解决
  • 做网站网站的给宝宝做衣服网站好
  • 网站建设一个人能做吗深圳小企业网站建设
  • 检索类的网站建设上饶市建设厅网站
  • wap网站的未来实名网站空间
  • 网站建设人员性格特点网站开发建设与维护
  • 有几个网站打不开seo技术学院
  • 框架网站建设广州网站建设外贸
  • 娱乐建设网站注册一个公司大概要多少钱
  • 为什么没人做同城购物网站宜春网站设计公司
  • 网站怎么吸引流量网店设计素材
  • 响应式网站的优势网站seo哪家公司好
  • 动漫设计培训机构哪里好龙岩seo推广
  • 佛山百度网站快速优化淘宝联盟做返利网站
  • apache新建网站番禺核酸检测点在哪
  • 中山如何建设网站阿里巴巴国际网站建设
  • 手机网站好处湖南湘江新区最新消息
  • cad线下培训班海南网站seo
  • 小说短篇做的好的网站怎么用VS2012建设网站
  • 做网站哪个语言好企业网站一般做多宽