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[30010];
bitset <30010> s[30010];
inline int read() {
    int x=0,f=1; char c=getchar();
    while(c<‘0‘||c>‘9‘) { if(c==‘-‘) f=-1; c=getchar(); }
    while(c>=‘0‘&&c<=‘9‘) { x=x*10+c-‘0‘; c=getchar(); }
    return x*f;
}
void add(int x,int y) {
    e[++tot].to=y,e[tot].next=head[x];
    head[x]=tot,deg[y]++;
}
void topsort() {
    queue<int> q;
    for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
    while(q.size()) {
        int x=q.front(); q.pop();
        topn[++cnt]=x;
        for(int i=head[x];i;i=e[i].next) {
            int to=e[i].to; deg[to]--;
            if(!deg[to]) q.push(to);
        }
    }
}
int main() {
    n=read(),m=read();
    for(int i=1;i<=m;i++) {
        int a,b;
        a=read(),b=read();
        add(a,b);
    }
    topsort();
    for(int i=cnt;i>=1;i--) {
        int x=topn[i];
        s[x][x]=1;
        for(int j=head[x];j;j=e[j].next) {
            int to=e[j].to;
            s[x]|=s[to];
        }
    }
    for(int i=1;i<=n;i++) printf("%d\n",s[i].count());
    return 0;
}

原文地址:https://www.cnblogs.com/Willendless/p/9514511.html

时间: 2024-11-08 03:47:59

2101 可达性统计的相关文章

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$ 出发所能到达的所有点的集合,应有

【CH2101】 可达性统计 解题报告

CH2101 可达性统计 描述 给定一张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 思路 我们可以利用记忆化搜索,对于每个点,记录它能到达的点的集合. 至于怎么记

可达性统计

可达性统计 给出一个n个点m条边的有向无环图,求每个点能到达的点的数目,\(n,m\leq 30000\). 解 设\(f[i]\)表示点i能到达的点的状态(其中1表示能够到达,0表示不能到达),显然有30000个点,所以我们无法用long long存下,于是用bitset,问题在于这个方程没有明显的阶段,不能循环实现,于是可以考虑拓扑排序或者是dfs. 参考代码: #include <iostream> #include <cstdio> #include <bitset&

「拓扑排序」可达性统计

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

【CH2101】可达性统计

这道题算是搜索和状压的结合吧,作为状压的入门题还是不错的,能让人初步了解状压的含义及应用. 对这张图进行一遍拓扑排序,然后状压统计(我用了bitset). 注意读入,因为我的读入优化挂掉了…… 1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <bitset> 5 using namespace std; 6 int n,m; 7 struct edge { 8 i

AcWing&#160;164.&#160;可达性统计

给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能够到达的点的数量. 数据范围 1≤N,M≤30000 显然可以用拓扑排序+状态压缩来做, 用一个n位的二进制数存每一个f[x], 其中第i位是1表示x能到i,0则不能到i, 这样就相当于存在x 到 y的一条边,f[x] |= f[y], 再预处理处拓扑序, 反向枚举, 最后判断每个f[i]中的个数,

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 算法:拓扑排序 + 状态压缩算法 题解:首先求出该有向无环图的拓扑

AW164 可达性统计

题目地址 注意点: 使用dfs的原因是后面的点会对之前点产生影响. #include<cstdio> #include<iostream> #include<bitset> using namespace std; const int MAXN=3e4+5,MAXM=3e4+5; struct Edge{ int from,to,nxt; }e[MAXM]; int head[MAXN],edgeCnt=1; void addEdge(int u,int v){ e[+

0x20 搜索

这里基本就是入门吧. 可达性统计 用bitset搞的判重,发现这东西是真好用哈,空间还小 #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<map> #include<bitset> using namespace std; ma