Tarjan&&缩点简析
由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan
Tarjan的思想其实很简单,就是用时间戳(讲得真TM流弊,其实就是DFS访问到的次序)和栈来搞一下
关于Tarjan的写法,我自己也不是很讲得来,大家可以看一下这篇blog
这里讲一下如何用Tarjan来进行缩点
令我们求出的col[i]表示原图中第i个点是哪个强连通分量中的,则我们可以建出新图,方式如下
for (i=1;i<=n;++i)
for (j=head[i];j!=-1;j=e[j].next)
if (col[i]!=col[e[j].to]) add(col[i],col[e[j].to]);
很玄学?但是它就是正确的,然后我们就得到了缩过点的新图
像有这里有一道模板题:Luogu P3387 【模板】缩点
题意很简单,我们先Tarjan缩点,缩完的点的点权就是它这个强连通分量中的所有点的点权和
然后就是一个DAG(有向无环图)了,我们DP,记搜,拓扑排序都可以
这里我还是习惯性的写了BFS的topo
CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e4+5,M=1e5+5;
struct edge
{
int to,next;
}e[M],ne[M];
int n,m,head[N],nhead[N],a[N],v[N],dfn[N],low[N],stack[N],col[N],dis[N],q[N],ru[N],top,cnt,x,y,tot,sum;
bool vis[N];
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void add(int x,int y)
{
e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline void nadd(int x,int y)
{
ne[++cnt].to=y; ne[cnt].next=nhead[x]; nhead[x]=cnt;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
inline void Tarjan(int now)
{
dfn[now]=low[now]=++tot;
stack[++top]=now; vis[now]=1;
for (register int i=head[now];i!=-1;i=e[i].next)
if (!dfn[e[i].to])
{
Tarjan(e[i].to);
low[now]=min(low[now],low[e[i].to]);
} else
{
if (vis[e[i].to]) low[now]=min(low[now],dfn[e[i].to]);
}
if (dfn[now]==low[now])
{
col[now]=++sum;
v[sum]+=a[now]; vis[now]=0;
while (now!=stack[top])
{
col[stack[top]]=sum;
v[sum]+=a[stack[top]]; vis[stack[top--]]=0;
} --top;
}
}
inline int topo(void)
{
memset(dis,0,sizeof(dis));
register int i; int ans=0;
int H=0,T=0;
for (i=1;i<=sum;++i)
if (!ru[i]) q[++T]=i,dis[i]=v[i],ans=max(dis[i],ans);
while (H<T)
{
int now=q[++H];
for (i=nhead[now];i!=-1;i=ne[i].next)
{
dis[ne[i].to]=max(dis[ne[i].to],dis[now]+v[ne[i].to]);
ans=max(ans,dis[ne[i].to]);
if (!(--ru[ne[i].to])) q[++T]=ne[i].to;
}
}
return ans;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
memset(head,-1,sizeof(head));
memset(e,-1,sizeof(e));
read(n); read(m);
for (i=1;i<=n;++i)
read(a[i]);
for (i=1;i<=m;++i)
read(x),read(y),add(x,y);
for (i=1;i<=n;++i)
if (!dfn[i]) Tarjan(i);
memset(nhead,-1,sizeof(head));
memset(ne,-1,sizeof(e)); cnt=0;
for (i=1;i<=n;++i)
for (j=head[i];j!=-1;j=e[j].next)
if (col[i]!=col[e[j].to]) nadd(col[i],col[e[j].to]),++ru[col[e[j].to]];
printf("%d",topo());
return 0;
}
Tarjan&&缩点简析的更多相关文章
- 简析.NET Core 以及与 .NET Framework的关系
简析.NET Core 以及与 .NET Framework的关系 一 .NET 的 Framework 们 二 .NET Core的到来 1. Runtime 2. Unified BCL 3. W ...
- 简析 .NET Core 构成体系
简析 .NET Core 构成体系 Roslyn 编译器 RyuJIT 编译器 CoreCLR & CoreRT CoreFX(.NET Core Libraries) .NET Core 代 ...
- hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)
#1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...
- POJ 1236 Network of Schools(Tarjan缩点)
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16806 Accepted: 66 ...
- King's Quest —— POJ1904(ZOJ2470)Tarjan缩点
King's Quest Time Limit: 15000MS Memory Limit: 65536K Case Time Limit: 2000MS Description Once upon ...
- RecycleView + CardView 控件简析
今天使用了V7包加入的RecycleView 和 CardView,写篇简析. 先上效果图: 原理图: 这是RecycleView的工作原理: 1.LayoutManager用来处理RecycleVi ...
- 【BZOJ-2438】杀人游戏 Tarjan + 缩点 + 概率
2438: [中山市选2011]杀人游戏 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1638 Solved: 433[Submit][Statu ...
- 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP
1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 787 Solved: 318[Submit][Stat ...
- Java Android 注解(Annotation) 及几个常用开源项目注解原理简析
不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...
随机推荐
- CVE-2018-18820 icecast 栈缓冲区越界写漏洞分析
前言 icecast 是一款开源的流媒体服务器 , 当服务器配置了 url 认证时,服务器在处理 HTTP 头部字段时错误的使用了 snprintf 导致栈缓冲区的越界写漏洞( CVE-2018-18 ...
- 二叉搜索树(Binary Search Tree)实现及测试
转:http://blog.csdn.net/a19881029/article/details/24379339 实现代码: Node.java //节点类public class Node{ ...
- [Ubuntu] 解决 ubuntu 升级时 /boot 空间不足
经常升级Linux内核,导致更新时警告/boot分区空间不足.这是以为多次升级内核后,导致内核版本太多,清理一下没用的内核文件就行了. 原文地址请保留http://www.cnblogs.com/ro ...
- Python+Selenium笔记(十四)鼠标与键盘事件
(一) 前言 Webdriver高级应用的API,允许我们模拟简单到复杂的键盘和鼠标事件,如拖拽操作.快捷键组合.长按以及鼠标右键操作,都是通过使用webdriver的Python API 中的Ac ...
- 学习笔记:The Best of MySQL Forum
http://mysql.rjweb.org/bestof.html I have tagged many of the better forum threads. 'Better' is based ...
- sql server 2008 身份验证失败 18456
双击打开后加上 ;-m 然后以管理员方式 打开 SQLSERVER 2008 就可以已window身份登录 不过还没有完 右键 属性 =>安全性 更改为 sql server 和 ...
- cd mkdir mv cp rm 命令目录相关操作
切换目录: cd 家目录 cd. 当前目录 cd.. 当前上一级目录 cd../../当前目录的上上级目录 cd - 返回前一个目录 --------------------------------- ...
- soapui 调用wsdl 步骤以及出现的问题
创建soap project 添加wsdl 地址(或者导入wsdl(后缀可以是xml或者wsdl)文件) 添加request 自动生成请求代码 参数放在in0 中 <soapenv:Envelo ...
- 将 SecondaryNameNode 配置到 s105 节点上
相关链接 Hadoop 完全分布式安装 0. 说明 SecondaryNameNode 的作用 参考[待补充] 在 Hadoop 完全分布式的基础之上配置 将 SecondaryNameNode ...
- SDN2017 期末作业验收
GIT仓库:GITHUB 负载均衡程序 拓扑如图 目的 实现一个负载均衡的北向程序: 服务器host 2 ,host 3,host 4上各自有不同的服务,host 1是客户端 当host 2,host ...