CH 2101 - 可达性统计 - [BFS拓扑排序+bitset状压]

题目链接:传送门

描述

给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。N,M≤30000。

输入格式

第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边。

输出格式

共N行,表示每个点能够到达的点的数量。

样例输入

10 10
3 8
2 3
2 5
5 9
5 9
2 3
3 9
4 8
2 10
4 9

样例输出

1
6
3
3
2
1
1
1
1
1

题解:

首先,如果用 $f(x)$ 代表从点 $x$ 出发所能到达的所有点的集合,应有如下公式:

$f(x) = {x} \cup (\bigcup_{edge(x,y)}f(y))$

也就是说我们可以通过某种递推方式,递推出所有点的 $f(x)$。

由此想到有向无环图的拓扑序(对于图中任意一条有向边 $(x,y)$,在该序列中 $x$ 都出现在 $y$ 之前),对有向无环图的拓扑序逆向遍历计算,正好可以正确求出每个点的 $f(x)$。

另外, 我们还可以用状压的方式来存储 $f(x)$,也比较方便转移和存储,这里我们用bitset容器来做状压。

关于bitset:

bitset<1000> num; 相当于定义了一个1000位的二进制数,其 $1$ 位占用 $1$ 个bit,也就是说 $8$ 位占用一个Byte。

由于估计时间复杂度是我们一般以 $32$ 位整数的运算次数为基准,因此 $n$ 位的bitset执行一次位运算的时间复杂度可以视作 $n/32$。

bitset支持的位运算有按位取反“~”、按位与“&”、按位或“|”、按位异或“^”、左移“<<”、右移“>>”(均用 $0$ 填充),还可以比较是否相等“==”和“!=”。

bitset支持 num[k] 这种形式进行取值或者赋值。根据上面的定义,范围为 num[0] 到 num[999] 。

bitset还支持:set()全部置 $1$、reset()全部置 $0$、count()统计 $1$ 的数目、any()查询是否存在 $1$、none()查询是否没有 $1$。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=30000+5;
int n,m;
int indg[maxn];
vector<int> e[maxn];
bitset<maxn> f[maxn];

vector<int> topo;
void TopoSort()
{
    topo.clear();
    queue<int> Q;
    for(int i=1;i<=n;i++) if(indg[i]==0) Q.push(i);
    while(Q.size())
    {
        int u=Q.front(); Q.pop();
        topo.push_back(u);
        for(auto v:e[u]) if(--indg[v]==0) Q.push(v);
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin>>n>>m;
    memset(indg,0,sizeof(indg));
    for(int i=1,x,y;i<=m;i++) cin>>x>>y, indg[y]++, e[x].push_back(y);

    TopoSort();
    for(int i=topo.size()-1;i>=0;i--)
    {
        int x=topo[i];
        f[x].reset(), f[x][x]=1;
        for(auto y:e[x]) f[x]|=f[y];
    }
    for(int i=1;i<=n;i++) cout<<f[i].count()<<endl;
}

原文地址:https://www.cnblogs.com/dilthey/p/10241928.html

时间: 2024-10-29 19:09:44

CH 2101 - 可达性统计 - [BFS拓扑排序+bitset状压]的相关文章

AcWing:164. 可达性统计(拓扑排序 + 状态压缩算法)

给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能够到达的点的数量. 数据范围 1≤N,M≤300001≤N,M≤30000 输入样例: 10 10 3 8 2 3 2 5 5 9 5 9 2 3 3 9 4 8 2 10 4 9 输出样例: 1 6 3 3 2 1 1 1 1 1 算法:拓扑排序 + 状态压缩算法 题解:首先求出该有向无环图的拓扑

2101 可达性统计

[题目描述] 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. [题目链接] 2101 可达性统计 [算法] 拓扑排序之后逆序计算,bitset状态压缩模拟集合的并操作. [代码] #include <bits/stdc++.h> using namespace std; int n,m,tot,cnt; struct edge{ int to,next; }e[30010]; int head[30010],topn[30010],deg[300

bfs 拓扑排序 bnu Usoperanto

题目链接:http://acm.bnu.edu.cn/v3/problem_show.php?pid=39572 题目详细分析:http://talk.icpc-camp.org/d/127-jag-summer-2012-day-4-j-usoperanto 对于这个题目,自己的一点补充(bfs 拓扑排序):在建树的时候,每建立一条边,父亲节点出度+1,因此树叶子节点的出度是为0的(题解里说的入度其实就是在建边的时候父亲节点的出度):那么把所有出度为0的节点压入队列,然后计算这些出度为0的节点

NOIP 车站分级 (luogu 1983 &amp; codevs 3294 &amp; vijos 1851) - 拓扑排序 - bitset

描述 一条单向的铁路线上,依次有编号为 1, 2, ..., n 的 n 个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站.终点站之间所有级别大于等于火车站 x 的都必须停靠.(注意:起始站和终点站自然也算作事先已知需要停靠的站点)例如,下表是 5 趟车次的运行情况.其中,前 4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求

[JSOI2019]精准预测(2-SAT+拓扑排序+bitset)

设第i个人在t时刻生/死为(x,0/1,t),然后显然能够连上(x,0,t)->(x,0,t-1),(x,1,t)->(x,1,t+1),然后对于每个限制,用朴素的2-SAT连边即可. 但这样的点数达到了O(nT),其实有一种方法可以只把限制的边连接建图,点数为4m,这样可能会被卡常. 有没有更优秀的做法?当然还是有的.对于2-SAT中的边(x,y),若y在2-SAT中无出边,则x->y与x->y的后继等价,于是点数可以控制在2n+2m.然后很容易发现,生.死状态的图均为拓扑图,而

poj1753 bfs+奇偶性减枝//状压搜索

http://poj.org/problem?id=1753 题意:有个4*4的棋盘,上面摆着黑棋和白旗,b代表黑棋,w代表白棋,现在有一种操作,如果你想要改变某一个棋子的颜色,那么它周围(前后左右)棋子的颜色都会被改变(白变成黑,黑变成白),问你将所有棋子变成白色或者黑色最少的步数. 思路: 1.如果用一个4*4的数组存储每一种状态,不但存储空间很大,而且在穷举状态时也不方便记录.因为每一颗棋子都只有两种状态,所以可以用二进制0和1表示每一个棋子的状态,则棋盘的状态就可以用一个16位的整数唯一

hdu 1811 Rank of Tetris(拓扑排序+并查集)

1 #include "cstdio" 2 #include "iostream" 3 #include "cstring" 4 #include "vector" 5 #include "queue" 6 using namespace std; 7 const int N = 10005; 8 int n, m, t; 9 int fa[N]; 10 int rank[N]; 11 int X[2*N]

「拓扑排序」可达性统计

可达性统计 原题链接:可达性统计 题目大意 给你一张\(n\)个点\(m\)条边的有向无环图,分别统计从每个点出发能够到达的点的数量 题目题解 看到题意就知道要用到拓扑排序,但是拓扑排序的理论复杂度在30000的极限条件下会超时,这个时候我们考虑使用 \(bitset\),一个很好用的代替bool的防卡常技巧,详细的说明这里不说,可以去百度上查看相关运用 //#define fre yes #include <queue> #include <bitset> #include &l

图论 邻接链表存储 BFS DFS 拓扑排序

package Algorithms; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.Stack; public class Graphic { public static class Vertex{ public int num;//节点编号 public int weight;//边的权重 public Vertex next;//指向顶点的