拓扑排序

「拓扑排序」可达性统计

余生颓废 提交于 2019-11-30 03:14:40
可达性统计 原题链接: 可达性统计 题目大意 给你一张 \(n\) 个点 \(m\) 条边的有向无环图,分别统计从每个点出发能够到达的点的数量 题目题解 看到题意就知道要用到拓扑排序,但是拓扑排序的理论复杂度在30000的极限条件下会超时,这个时候我们考虑使用 \(bitset\) ,一个很好用的代替bool的防卡常技巧,详细的说明这里不说,可以去百度上查看相关运用 //#define fre yes #include <queue> #include <bitset> #include <cstdio> #include <cstring> #include <algorithm> const int N = 30005; int head[N << 1], to[N << 1], ver[N << 1]; int in[N], ans[N]; std::bitset<N> f[N]; int tot, k; void addedge(int x, int y) { ver[tot] = y; to[tot] = head[x]; head[x] = tot++; } int n, m; void toposort() { std::queue<int> q; for (int i = 1; i <= n; i++) { if(!in[i]) q.push(i); } while

『拓扑排序』拓扑排序模板

倖福魔咒の 提交于 2019-11-30 03:13:42
拓扑排序学习前提须知 拓扑排序是对于一个图的所有节点进行排序,要求排序完后没有一个节点指向它前面的节点,那么这样我们就会得到一个拓扑排序后的数组,我们从后往前扫通过某种计算就能够得到从某一个点开始最多能到多少个点。 算法内容 竞赛需要用到的点 1、拓扑排序仅适用于有向无环图,当然也可以判定是否图为无环图 2、能够得到从一个点能到多少个其他的点,如果n在万以上,处理得当甚至能够过千万 拓扑排序略讲 拓扑排序需要满足一个很重要的条件就是,每次进入答案的点的入度一定为0,那么根据这个条件,我们就能得到我们的拓扑排序后的数组 void toposort() { std::queue<int> q; //存储到目前为止入度为0的点 std::vector<int> ans; //储存答案 for (int i = 1; i <= n; i++) { if(!in[i]) q.push(i); //如果入度为0则加入队列中 } while(!q.empty()) { //简单的搜索 int t = q.front(); q.pop(); ans.push_back(t); for (int i = head[t]; ~i; i = to[i]) { int v = ver[i]; if(!in[v]) q.push(v); } } for (int i = 0; i < n; i++) { /

Java 反序列化工具 gadgetinspector 初窥

廉价感情. 提交于 2019-11-30 02:42:43
作者:Longofo@知道创宇404实验室 时间:2019年9月4日 原文链接 :https://paper.seebug.org/1034/ 起因 一开始是听@Badcode师傅说的这个工具,在Black Hat 2018的一个议题提出来的。这是一个基于字节码静态分析的、利用已知技巧自动查找从source到sink的反序列化利用链工具。看了几遍作者在Black Hat上的 演讲视频 与 PPT ,想从作者的演讲与PPT中获取更多关于这个工具的原理性的东西,可是有些地方真的很费解。不过作者开源了这个 工具 ,但没有给出详细的说明文档,对这个工具的分析文章也很少,看到一篇平安集团对这个工具的 分析 ,从文中描述来看,他们对这个工具应该有一定的认识并做了一些改进,但是在文章中对某些细节没有做过多的阐释。后面尝试了调试这个工具,大致理清了这个工具的工作原理,下面是对这个工具的分析过程,以及对未来工作与改进的设想。 关于这个工具 这个工具不是用来寻找漏洞,而是利用已知的source->...->sink链或其相似特征发现分支利用链或新的利用链。 这个工具是在整个应用的classpath中寻找利用链。 这个工具进行了一些合理的预估风险判断(污点判断、污点传递等)。 这个工具会产生误报不是漏报(其实这里还是会漏报,这是作者使用的策略决定的,在后面的分析中可以看到)。 这个工具是基于字节码分析的

拓扑排序学习笔记

Deadly 提交于 2019-11-30 01:40:29
拓扑排序 1.拓扑排序只对于 有向无环图 而言 (Directed Acyclic Graph简称DAG) 2.在一个有向无环图中,若a–>b–>c,则拓扑序列为 (a,b,c);也就是说如果一条边a—>b,那么在拓扑序列里a就在b前面; 知道了这两点,那么就可以来求拓扑序列了; 首先,我们知道在DAG中一定存在一个入度为0的点,那么这个点就是我们的起始点;根据这个点我们就可以通过bfs往后找,每找到一个相连点,就把这一条边删去,怎么删呢? 比如我们从a点开始,发现a与b相连,我们就要把a–>b这条边删去,就是b的入度减一,当发现一个点的入度为0时,就把这个点入队,并且用容器存下这个点;所得的容器里面的序列就是拓扑序列; 代码实现十分简单; 模板题: 给定一个n个点m条边的有向图,图中可能存在重边和自环。 请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。 若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。 输入格式 第一行包含两个整数n和m 接下来m行,每行包含两个整数x和y,表示存在一条从点x到点y的有向边(x, y)。 输出格式 共一行,如果存在拓扑序列,则输出拓扑序列。否则输出-1。 代码: # include <bits/stdc++.h> # define LL long long #

洛谷p2149----两个终点和两个起点,最短路最大交汇长度!!!

拈花ヽ惹草 提交于 2019-11-29 21:27:09
说实话,这题真第一次见,学到了不少有趣的东西,因吹丝汀!! 思路:因为不可能同时并行和相遇(我也不知道为啥,等我会证明了就来说说) 所以正向建边再反向建边,拓扑排序+dp求最下长路,记录下最大的就是解 高中生的OI题好难呀 #include<iostream> #include<vector> #include<cstring> #include<cstdio> #include<queue> #include<algorithm> #include<map> using namespace std; #define maxn 2000 const int mod = 10000; map<long long, int>ins; struct Node { int p; int len; Node(int a, int b) :p(a), len(b) {} }; bool operator < (const Node a, const Node b) { return a.len > b.len; } vector<Node>G[maxn], G2[maxn]; int vis[maxn]; void insert(int be, int en, int len) { G[be].push_back(Node(en, len)); } int dijstra(int be,

拓扑排序入门

时间秒杀一切 提交于 2019-11-29 19:19:20
拓扑排序入门 2018年06月25日 19:15:30 独- 阅读数 29543 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/qq_41713256/article/details/80805338 在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。 先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一。 一直做改操作,直到所有的节点都被分离出来。 如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序,也就是很多题目的无解的情况。 下面是算法的演示过程。 下面是我以前的写法,比较好理解,但是效率低 //b[]为每个点的入度 for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(b[j]==0){ //找到一个入度为0的点 ans=j; vis[cnt++]=j; b[j]--; break; } } for(j=1;j<=n;j++) if(a[ans][j]) b[j]--; //与入度为0的点相连的点的入度减一 } printf("%d",vis[0]); for(i=1;i<cnt;i++) printf(" %d",vis[i]); printf("\n");

图论排序---拓扑排序

青春壹個敷衍的年華 提交于 2019-11-29 19:18:23
定义 对于有向无权无环图,进行拓扑排序 实现方式 Kahn算法 基于DFS的拓扑排序算法 Kahn算法 排序的过程 1.对于DAG,先输出没有前驱的点 2.把与前驱相关的边删除 3.继续输出没有前驱的点 4.重复前者,直到DAG为空或者没有前驱 如果我们有如下的一个有向无环图,我们需要对这个图的顶点进行拓扑排序,过程如下: 首先,我们发现V6和v1是没有前驱的,所以我们就随机选去一个输出,我们先输出V6,删除和V6有关的边,得到如下图结果: 然后,我们继续寻找没有前驱的顶点,发现V1没有前驱,所以输出V1,删除和V1有关的边,得到下图的结果: 然后,我们又发现V4和V3都是没有前驱的,那么我们就随机选取一个顶点输出(具体看你实现的算法和图存储结构),我们输出V4,得到如下图结果: 然后,我们输出没有前驱的顶点V3,得到如下结果: 然后,我们分别输出V5和V2,最后全部顶点输出完成,该图的一个拓扑序列为: v6–>v1—->v4—>v3—>v5—>v2 应用 给出n个点,m个关系 再给出u,v,表示u比v厉害 然后进行排序 邻接矩阵版Kahn算法的拓扑排序 传送门 裸拓扑排序 #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int

拓扑排序

淺唱寂寞╮ 提交于 2019-11-29 17:09:42
# include <iostream> # include <algorithm> # include <cstring> # include <string> # include <sstream> # include <cstdio> # include <vector> # include <queue> using namespace std ; const int MAXN = 10017 ; # define pii pair<int, int> int n , tot ; vector < int > G [ MAXN ] ; vector < pii > task [ MAXN ] ; bool vis [ 500000 ] ; int deg [ 500000 ] ; int dict [ MAXN ] [ 100 ] ; int work ( ) { //init tot = 0 ; memset ( vis , 0 , sizeof ( vis ) ) ; memset ( deg , 0 , sizeof ( deg ) ) ; memset ( dict , 0 , sizeof ( dict ) ) ; for ( int i = 0 ; i < n ; i ++ ) task [ i ] . clear ( ) ; //read for ( int

拓扑排序的小总结

↘锁芯ラ 提交于 2019-11-29 14:21:07
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 100 + 15; int n,m,t;//图中有n个节点 int topo[maxn];//储存拓扑排序的顺序 int staus[maxn];//表示转态 bool Grape[maxn][maxn];//表示依赖关系 bool dfs(int u) { staus[u] = -1;//表示正在进行深搜 for(int v=1;v<=n;++v) { if(Grape[u][v]) { if(staus[v]<0) return false;//说明存在环 if(!staus[v]&&!dfs(v))//如果未被访问过 return false; } } staus[u] = 1;//表示已经深搜完并返回的状态 topo[--t] = u; return true; } bool topoSort() { t = n; memset(staus,0,sizeof(staus));//节点都未被访问过 for(int u=1;u<=n;++u)//深搜每一个节点 { if(!staus[u])//当未访问过 if(!dfs(u)) return false; } return true; } int

拓扑排序

余生颓废 提交于 2019-11-29 11:55:47
拓扑排序 类似于a<b,c<b,d<c,可以找到一个关系是a<d<c<b。意思就是有好几件事ABCD,B要在A后面做,C要在B后面做等等,然后对每个事件的先后顺序进行排序。 做法就是每次删除一个入度为零的点,而这个点指向的点的入度就减一,循环下去直到所有结点被找出来。如果排序失败,表示有环。 #include<iostream> #include<algorithm> #include<stdio.h> #include<cmath> #include<cstring> #define MAXN 517 using namespace std; int G[MAXN][MAXN]; int ds[MAXN]; int ans[MAXN]; int n, m, x, y; int i, j; void tp(); void init(); int main() { while (cin >> n >> m) { init(); for (i = 0;i < m;i++) { cin >> x >> y; G[x][y] = 1; } tp(); for (i = 1;i < n;i++) { cout << ans[i] << ' '; } cout << ans[n] << endl; } } void tp() { for (i = 1; i <= n; i++) { for