164. 可达性统计(拓扑排序,位运算,状压)

2024-02-15 09:44

本文主要是介绍164. 可达性统计(拓扑排序,位运算,状压),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

164. 可达性统计 - AcWing题库

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

输入格式

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

输出格式

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

数据范围

1≤N,M≤30000
1≤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

解析: 

因为本题的图示有向无环图,及不存在后效性问题(循环依赖),所以我们可以使用dp来处理本问题。 

f[i]表示所有i能到的点的集合: 
f[i]=i|f[j1]|f[j2]|f[j3]…… 

那么此时问题在于由于数据量很大,所以我们不能使用传统的状态压缩(因为数字会爆longlong),但我们可以使用bitset来压缩(原理和状态压缩相同,只不过没有位数限制)。 

 

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 3e4 + 5, M = 3e4 + 5, INF = 0x3f3f3f3f;
int n, m;
int h[N], e[M], ne[M], idx;
int q[N], d[N];
bitset<N>f[N];void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}void topsort() {int hh = 0, tt = 0;for (int i = 1; i <= n; i++) {if (!d[i]) q[tt++] = i;}while (hh < tt) {int t = q[hh++];for (int i = h[t]; i != -1; i = ne[i]) {int j = e[i];if (--d[j] == 0) {q[tt++] = j;}}}
}int main() {cin >> n >> m;memset(h, -1, sizeof h);for (int i = 1,a,b; i <= m; i++) {scanf("%d%d", &a, &b);add(a, b);d[b]++;}topsort();for (int i = n - 1; i >= 0; i--) {int j = q[i];f[j][j] = 1;for (int k = h[j]; k != -1; k = ne[k]) {f[j] |= f[e[k]];}}for (int i = 1; i <= n; i++)printf("%d\n", f[i].count());return 0;
}

这篇关于164. 可达性统计(拓扑排序,位运算,状压)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/711035

相关文章

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

uva 575 Skew Binary(位运算)

求第一个以(2^(k+1)-1)为进制的数。 数据不大,可以直接搞。 代码: #include <stdio.h>#include <string.h>const int maxn = 100 + 5;int main(){char num[maxn];while (scanf("%s", num) == 1){if (num[0] == '0')break;int len =

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

hdu4267区间统计

题意:给一些数,有两种操作,一种是在[a,b] 区间内,对(i - a)% k == 0 的加value,另一种操作是询问某个位置的值。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import

hdu4417区间统计

给你一个数列{An},然后有m次查询,每次查询一段区间 [l,r] <= h 的值的个数。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamRead