缩点。算法
顾名思义,就是在图论算法中将一些点缩成一个点的一种算法。数组
貌似明白了,可是这有什么用呢?code
咱们常常求最短路,可是若是咱们要求最长路呢?blog
标准问法:图片
给你一张有向图,每一个点都有一个点权(不是边权了哦),且每个点均可以通过任意屡次,可是点权只能加一次,求这张图的最大权值get
题目分析:io
看到这,相信大多数人都会想到把最短路的模板改一下就好了,可是这会出问题,你会在一个圈里团团转。模板
怎么办办?class
咱们会发现,只要是一堆能够构成强连通份量的点,咱们就能够将它们缩成一个点,而这个点的点权就是它们的点权和,它的入边就是它们全部点的入边,出边就是它们全部点的出边。遍历
放几张图有助于理解:
上图中1.3.5就是一个强连通份量
咱们在tarjan求强连通份量时开过一个数组叫作color[](或其余名字)
来记录一个点 所属于的强连通份量编号。因此咱们能够遍历每个点,看看它所能到达的点是否和它同处于同一个强连通份量中,若不是,则依托它们强连通份量的编号再构建一个有向无环图 (想想,为何要依托编号)
for(int i=1;i<=n;i++) { for(int j=0;j<ver[i].size();j++) { int x=ver[i][j]; if(color[i]!=color[x]) { in[color[x]]++; g[color[i]].push_back(color[x]); } } } for(int i=1;i<=n;i++) ww[color[i]]+=w[i];//点权处理
这样咱们就实现了缩点。