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

算法:拓扑排序 + 状态压缩算法

题解:首先求出该有向无环图的拓扑序列,根据拓扑序列的性质:在拓扑序种,对于任意一条边(x, y)来说,x都会排在y之前(读者可以自行画图证明)。然后倒叙遍历拓扑序来结果状态压缩来求的结果。

#include <iostream>
#include <cstdio>
#include <vector>
#include <bitset>
#include <queue>

using namespace std;

const int maxn = 3e4+7;

vector<int> g[maxn];
vector<int> a;
bitset<maxn> f[maxn];

int in[maxn];
int n, m;

void topsort() {
    queue<int> q;
    for(int i = 1; i <= n; i++) {
        if(in[i] == 0) {
            q.push(i);
        }
    }
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        a.push_back(u);     //记录拓扑序列
        int len = g[u].size();
        for(int i = 0; i < len; i++) {
            int v = g[u][i];
            if(--in[v] == 0) {
                q.push(v);
            }
        }
    }
}

void sovle() {
    for(int i = a.size() - 1; i >= 0; i--) {
        int u = a[i];
        f[u].reset();   //清空数组
        f[u][u] = 1;    //将当前位置赋1
        int len = g[u].size();
        for(int j = 0; j < len; j++) {
            int v = g[u][j];
            f[u] = f[u] | f[v];     //将经过的点的状态压缩到当前数组中
        }
    }
}

int main() {
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        g[u].push_back(v);
        in[v]++;
    }
    topsort();
    sovle();
    for(int i = 1; i <= n; i++) {
        printf("%d\n", f[i].count());
    }
    return 0;
}

原文地址:https://www.cnblogs.com/buhuiflydepig/p/11336314.html

时间: 2024-11-08 03:48:00

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

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]中的个数,

「拓扑排序」可达性统计

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

ZJU 1346 Comparing Your Heroes 状态压缩DP 拓扑排序的计数

做多校的时候遇见一个求拓扑排序数量的题,就顺便来写了一下. 题意: 你有个朋友是KOF的狂热粉丝,他有一个对其中英雄的强弱比较,让你根据这些比较关系来给这些英雄排名.问一共有多少种排名方式. 思路: 用dp[S]记录当前状态的数量. S表示拓扑排序中当前阶段已经被排序的点的集合.然后就可以枚举当前排序的点,转移的条件是这个点的所有前驱都被排序,而且这个点没被排序.然后转移就好了,最终状态就是所有点都完成排序. 代码: 1 #include <iostream> 2 #include <c

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

可达性统计

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

【数据结构】拓扑排序算法

对AOV网进行拓扑排序的基本思路是: 从AOV网中选择一个入度为0的顶点输出,然后删去此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者AOV网中不存在入度为0的顶点为止. AOV网及邻接表数据结构: 代码: #include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h"

图的拓扑排序

定义: 图的拓扑排序是对有向无环图来说的,无向图和有环图没有拓扑排序,或者说不存在拓扑排序,对于一个有向无环图G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若图G存在边< u, v >,则u在线性序列中出现在v之前.对一个有向无环图进行拓扑排序产生的线性序列称为满足拓扑次序的序列.一个有向无环图可以表示某种动作或者方案,或者状态,而有向无环图的拓扑序列通常表示某种某案切实可行或者各个成员之间的某种关系. 举个栗子,看上面那个图,v1v2v3v4v5v6v7v8是

强连通分量与拓扑排序略解

$ ??????????????? ? $强连通分量与拓扑排序 拓扑排序 $ ??????$对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前.通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列.简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序. (by 百度百科) $

拓扑排序之变量序列算法分析

拓扑排序之变量序列 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 题目描述: 假设有n个变量(1<=n<=26,变量名用单个小写字母表示),还有m个二元组(u,v),分别表示变量u小于v.那么,所有变量从小到大排列起来应该是什么样子的呢? 例如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b.尽管还有可能其他的可能,你只需找出其中的一个即可. 输入: 输入为一