ZOJ 3795 Grouping 强连通分量-tarjan
一开始我还天真的一遍DFS求出最长链以为就可以了
不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环图才行,这个时候再找最长链,当然缩点之后的scc是有权值的,不能只看成1,缩点完了之后,用记忆化搜索DP就可以再On的复杂度内求出结果
所以现学了一下SCC-Tarjan,所谓Scc-tarjan,就是找到强连通分量并且缩点,特别好用,其原理就是利用dfs时间戳,每个点有自己的时间戳,同时再开一个记录通过孩子的路径能指向的最上边的节点的时间戳,lowlink,如果当前lowlink就等于自己,即找到了强连通分量,并且找到了最大的头头。所以一个点也是强连通分量
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
const int N = ;
stack<int> sta;
vector <int> G[N];
vector <int> G4[N];
int vis[N];
int n,m;
int pre[N],lowlink[N],sccno[N],w[N],dfs_clk,scc_cnt;
int dp[N];
void init()
{
dfs_clk=scc_cnt=;
for (int i=;i<=n;i++){
G[i].clear();
pre[i]=;
lowlink[i]=;
sccno[i]=;
vis[i]=;
w[i]=;
G4[i].clear();
}
}
void dfs(int u)
{
pre[u]=lowlink[u]=++dfs_clk;
sta.push(u);
for (int i=;i<G[u].size();i++){
int v=G[u][i];
if (!pre[v]){
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if (!sccno[v]){
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if (lowlink[u]==pre[u]){
scc_cnt++;
for (;;){
int x=sta.top();sta.pop();
sccno[x]=scc_cnt;
w[scc_cnt]++;
if (x==u) break;
}
}
}
void tarjan()
{
for (int i=;i<=n;i++){
if (!pre[i]) dfs(i);
}
}
void calc(int u)
{
if (dp[u]!=-) return;
dp[u]=w[u];
int now=w[u];
for (int j=;j<G4[u].size();j++){
int v=G4[u][j];
calc(v);
dp[u]=max(dp[u],dp[v]+now);
}
}
void solve()
{
for (int i=;i<=n;i++){
int u=sccno[i];
for (int j=;j<G[i].size();j++){
int v=sccno[G[i][j]];
if (u!=v) G4[u].push_back(v);
}
}
for (int i=;i<=scc_cnt;i++){
dp[i]=-;
}
for (int i=;i<=scc_cnt;i++){
calc(i);
}
int ans=;
for (int i=;i<=scc_cnt;i++){
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
init();
int a,b;
while (m--)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
}
tarjan();
solve();
}
return ;
}
ZOJ 3795 Grouping 强连通分量-tarjan的更多相关文章
- ZOJ 3795 Grouping (强连通缩点+DP最长路)
<题目链接> 题目大意: n个人,m条关系,每条关系a >= b,说明a,b之间是可比较的,如果还有b >= c,则说明b,c之间,a,c之间都是可以比较的.问至少需要多少个集 ...
- 强连通分量(tarjan求强连通分量)
双DFS方法就是正dfs扫一遍,然后将边反向dfs扫一遍.<挑战程序设计>上有说明. 双dfs代码: #include <iostream> #include <cstd ...
- zoj 3795 Grouping tarjan缩点 + DGA上的最长路
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Submit Status Practic ...
- 有向图强连通分量 Tarjan算法
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
- POJ2186 Popular Cows 强连通分量tarjan
做这题主要是为了学习一下tarjan的强连通分量,因为包括桥,双连通分量,强连通分量很多的求法其实都可以源于tarjan的这种方法,通过一个low,pre数组求出来. 题意:给你许多的A->B ...
- ZOJ 3795 Grouping
大致题意是给n个人和m组关系,每组关系都是两个人s和t,表示s年龄不小于t的年龄,然后让你把这n个人分组,使得任何一个组里面的任意两人都不能直接或间接的得出这两个人的年龄大小关系. 思路:根据给出的关 ...
- [有向图的强连通分量][Tarjan算法]
https://www.byvoid.com/blog/scc-tarjan 主要思想 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的 ...
- 图的连通性:有向图强连通分量-Tarjan算法
参考资料:http://blog.csdn.net/lezg_bkbj/article/details/11538359 上面的资料,把强连通讲的很好很清楚,值得学习. 在一个有向图G中,若两顶点间至 ...
- 强连通分量tarjan缩点——POJ2186 Popular Cows
这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...
随机推荐
- 关于Simulink的sample time的问题
在对simulink建模的过程中,有时候会遇到sample time出现错误的问题,比如下图是我在使用simulink自带的Recursive least square Estimator最小二乘估计 ...
- Python学习第三课——运算符
# 运算符 + - * / **(幂) %(取余) //(取整) num=9%2 print("余数为"+(str)(num)) #运算结果为 1 num1=9//2 print( ...
- 【Python基础知识】【语法】【入门】
一.Python概述 Python是一门面向对象的编程语言,拥有强大丰富的库,没有操作系统的限制,是一种优美.清晰的编程语言. 二.Python基础语法 1.Python标识符 标识符就是程序中定义的 ...
- 树莓派frp添加为服务管理
1.下载frp https://github.com/fatedier/frp/releases 我是1代的B+,下载arm版的,新的可以用arm64的 frp_0.29.0_linux_arm.ta ...
- SQL常用关键字
常用SQL语句 SAP实际上提供了两种访问数据库的方式:Open SQL与Native SQL ---语句 功能 数据操作 insert 向表添加新数据行 delete 从表中删除数据行 upda ...
- ibd2sdi — InnoDB表空间SDI提取实用程序
参考mysql8.0官方文档 https://dev.mysql.com/doc/refman/8.0/en/ibd2sdi.html ibd2sdi是一个实用程序,用于从表空间文件中提取 序列化的字 ...
- 树莓派学习笔记——Restful服务 采用slim php apache
0.前言 前些时间沉迷于Restful,采用PHP+Slim+MySQL实现了一些简单的API函数.但是这些工作都是在windows中实现(采用wamp server集成安装包),但是转到li ...
- Java读取压缩文件信息
不解压压缩文件,获取其中包含的文件,通过文件名检查是否包含非法文件.(后续再根据文件头或内容吧) zip: import java.util.zip.ZipEntry;import java.util ...
- 编程题目 定义栈的数据类型,请在类型中实现一个能够得到栈最小元素的minx函数。
首先自己用 节点 实现了 栈 这种数据类型 为了实现题目了要求,我使用的两个栈. 一个栈 用来 push pop 用户的数据, 另外一个栈用来存放 最小元素(涉及元素比较) 代码如下: #!/usr/ ...
- 使用nginx做反向代理来访问tomcat服务器
本次记录的是使用nginx来做一个反向代理来访问tomcat服务器.简单的来说就是使用nginx做为一个中间件,来分发客户端的请求,将这些请求分发到对应的合适的服务器上来完成请求及响应. 第一步:安装 ...