Acwing 164.可达性统计(Java)
题目描述:
给定一张 N 个点 M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。
输入格式
第一行两个整数 N,M,接下来 M 行每行两个整数 x,y,表示从 x 到 y 的一条有向边。
输出格式
输出共 N 行,表示每个点能够到达的点的数量。
数据范围
1≤N,M≤30000
题目链接:可达性统计
思路:不能直接从某个结点向下去使用DFS查找它能到的点,因为对于a->b, a->c, b->d, c->d的情况,使用向下DFS得到 a 可达的点有4个,b , d , c , d,实际上只有3个,b , c, d。所有我们要另寻解法。
1.先根据各点入度进行拓扑排序,然后从后往前遍历各点能到的点,最后一个点只能到自身,若 i 点能到后面的某个点 j,则用 i 点并上后一个的点 j 能到的点的集合表示 i 能通过 j 到的所有点的集合。例如用 f(x)表示x能到的点的集合,假设 a 点能到的点是 b,b 点能到 c ,则a点能到的点的集合为:{a} U f (b) U f(c),因为是从后往前计算的,所以对于前一个点 i ,只需要并上后一个点 j 能到的集合即可,j 能到的所有点的集合肯定先算出来了的,即{a} U f (b)即可,f(b)已经是并上了f(c)的
2.用位图来存放每个点能否到其他点,对于第 i 位,1表示能到,0表示不能到,直接使用Java中的Bitset来处理,它有对应的进行位运算的方法。
下面的图表示位图的运算:
代码:
import java.util.ArrayList;
import java.util.BitSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;public class Main {static int[] de, sort; //各点入度、拓扑排序后的数组static int n, m; //点数和边数static ArrayList<ArrayList<Integer>> list = new ArrayList<>();//存放点的下一个点的集合static BitSet[] bitSets; //BitSet是位图 list.get(i)就是i点的下一个点的集合public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt(); m = sc.nextInt();de = new int[n+1];sort = new int[n+1];bitSets = new BitSet[n+1];//为位图数组申请空间for (int i = 0; i <= n; i++) {list.add(new ArrayList<>());//为集合分配空间bitSets[i] = new BitSet(); //为各个位图申请空间}for (int i = 1; i <= m; i++) {int a = sc.nextInt(), b = sc.nextInt();list.get(a).add(b); //b点存入a点集合de[b]++; //b点入度加一}topSort();solve();}public static void topSort() {//拓扑排序Queue<Integer> q = new LinkedList<>();for (int i = 1; i <= n; i++) if (de[i]==0)q.offer(i);int k = 1;while(!q.isEmpty()) {int a = q.poll();sort[k++] = a;ArrayList<Integer> tmp = list.get(a);for (Integer next : tmp) if (--de[next]==0)q.offer(next);}}public static void solve() {//位图的并集运算for (int i = n; i >= 1; i--) {int k = sort[i];bitSets[k].set(k);//set方法是使第k位变为1ArrayList<Integer> tmp = list.get(k);for (Integer next : tmp) {//当前点并上下一个能到点的能到的集合bitSets[k].or(bitSets[next]);//集合的并运算}}for (int i = 1; i <= n ;i++) {System.out.println(bitSets[i].cardinality());//输出位图中1的个数,表示能到的点数}}
}
Acwing 164.可达性统计(Java)相关推荐
- AcWing 164. 可达性统计
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能 ...
- 164. 可达性统计【拓扑排序 / bitset】
无环说明一定有拓扑排序. 我们得到拓扑排序,倒着推.注意压位. #include<bits/stdc++.h> #include<bitset> using namespace ...
- AcWing P164 可达性统计 题解
Analysis 这道题我一开始想到的是传递闭包,但是时间复杂度是n³,也开不下30000*30000的数组,所以我想到了拓扑+状态压缩(bitset),从后往前找,把能到达的点能到哪里用位运算赋到上 ...
- 统计java文件中的代码行数
统计Java代码行数工具类 -- CodeCounterUtil.java 统计指定目录下的java文件中代码行数 -- public static int getCodeNumFromFo ...
- P6134 [JSOI2015]最小表示(拓扑排序递推 + bitset优化,可达性统计变种)
整理的算法模板合集: ACM模板 P6134 [JSOI2015] 题目要求删除一条边整个图的连通性是不受影响的,也就是说如果我们要删除边(x,y)(x,y)(x,y),删除以后整个图的连通性不受影响 ...
- [2021-09-02 contest]CF1251C,可达性统计(bitset优化dp),Boomerang Tournament(状压dp),小蓝的好友(mrx)(treap平衡树)
文章目录 CF1251C Minimize The Integer acwing164:可达性统计 Facebook Hacker Cup 2016 Round 1 Boomerang Tournam ...
- linux中统计java数量,linux 统计当前目录下文件数
查看当前目录下文件的个数 ls -l | grep "^-" | wc -l 查看当前目录下文件的个数,包括子目录里的. ls -lR| grep "^-" | ...
- 「CH2101」可达性统计 解题报告
CH2101 可达性统计 描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到 ...
- 7-4 统计Java程序中关键词的出现次数 (25 分)
** 7-4 统计Java程序中关键词的出现次数 (25 分) ** 编写程序统计一个输入的Java源码中关键字(区分大小写)出现的次数.说明如下: Java中共有53个关键字(自行百度) 从键盘输入 ...
最新文章
- python 使用pymssql连接sql server数据库
- DexFile类介绍
- memwatch内存泄露检测工具
- 以管理员身份运行IJ
- linux ubantu扩展空间,ubuntu 扩展存储空间
- python要记多少个单词是合理的_词汇量少的人每天背多少单词合适?
- Tomcat启动提示At least one JAR was scanned for TLDs yet contained no TLDs
- 系统学习深度学习(二) --自编码器,DA算法,SDA,稀疏自编码器
- 2021-02-13
- [js]调用google,51ditu和mapbar的地图API
- Eclipse从零开始搭建一个SpringBoot项目
- android 实现按键精灵
- 转行计算机,如何成功进入大厂?
- tomcat启动异常:A child container failed during start
- MySQL实现定时任务
- 理想低通滤波器、Butterworth滤波器和高斯滤波器(matlab)
- 邀请试用 实景三维模型在线浏览及网页分享平台
- CodeForce 597ADivisibility
- python做正态分布的例子_Python求正态分布曲线下面积实例
- Codeforces Round #637 (Div. 2) - Thanks, Ivan Belonogov! C. Nastya and Strange Generator