接上一节 Tarjan算法初探(1):Tarjan如何求有向图的强连通分量

Tarjan算法一个非常重要的应用就是 在一张题目性质在点上性质能够合并的普通有向图中将整个强连通分量视作一个点来把整张图变成一张DAG(即有向无环图) 而DAG的形态满足最优子结构经常与DP联系在一起 故缩点常作为一条桥梁将图论DP相联系

缩点思想不难理解 这里主要说明一下代码的操作细节与流程:

1.使用Tarjan算法求出每个点属于哪一个强连通分量

2.枚举每一条点将每一个点对应性质合并到新的点上

3.枚举每一条边将每条边两端的点对应的新点相连来重构整张图(注意自环的问题) 重构时可能有的重边不影响重构图是一个DAG

其中 2 3 步可同时进行。

下面贴一道模板题来熟悉代码

洛谷:【模板】缩点

给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。 n<=10^4,m<=10^5,0<=点权<=1000

分析:

裸题 缩点以后直接DP完事 没有思维难度的DP

 #include <cstdio>
#include <iostream>
#define re register
#define r(x) x=read()
#define MAXX 10005
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
using namespace std;
int dfn[MAXX],low[MAXX],que[MAXX],ans[MAXX],w[MAXX],w2[MAXX],id[MAXX],
st[MAXX],top,u,to,n,m,cnt[],k,num,h[][MAXX],sum[MAXX];
struct edge{int to,nex;}e[][MAXX<<];
void add(int u,int to,int id)
{
++cnt[id];
e[id][cnt[id]]=(edge){to,h[id][u]};
h[id][u]=cnt[id];
}
int read()
{
char ch=;int w=,ff=;
while(ch<''||ch>''){if(ch=='-')ff=-;ch=getchar();}
while(ch>=''&&ch<=''){w=w*+ch-'';ch=getchar();}
return ff*w;
}
void tarjan(int now)//求强连通分量
{
low[now]=dfn[now]=++k;
st[++top]=now;
for(int i=h[][now];i;i=e[][i].nex)
{
if(!dfn[e[][i].to])
tarjan(e[][i].to),low[now]=MIN(low[now],low[e[][i].to]);
else
if(!id[e[][i].to])
low[now]=MIN(low[now],dfn[e[][i].to]);
}
if(low[now]==dfn[now])
{
id[now]=++num;
while(st[top]!=now)
{
id[st[top]]=num;
--top;
}
--top;
}
}
void build()//缩点
{
for(int i=;i<=n;++i)
{
w2[id[i]]+=w[i];//点权值合并
for(int j=h[][i];j;j=e[][j].nex)
if(id[i]!=id[e[][j].to])
add(id[i],id[e[][j].to],),++sum[id[e[][j].to]];//连边
}
for(int i=;i<=num;++i)
if(sum[i]==) que[++top]=i,ans[que[top]]+=w2[que[top]];
for(int i=;i<=top;++i)
{
for(int j=h[][que[i]];j;j=e[][j].nex)
{
sum[e[][j].to]--;
if(!sum[e[][j].to]) que[++top]=e[][j].to;
}
}//拓扑排序
}
void solve()//裸DP
{
for(int i=;i<=top;++i)
for(int j=h[][que[i]];j;j=e[][j].nex)
ans[e[][j].to]=MAX(ans[e[][j].to],w2[e[][j].to]+ans[que[i]]);
int maxx=;
for(int i=;i<=num;++i)
maxx=max(maxx,ans[i]);
printf("%d",maxx);
}
void input()
{
r(n),r(m);
for(re int i=;i<=n;++i)
r(w[i]);
for(re int i=;i<=m;++i)
r(u),r(to),add(u,to,);
}
int main()
{
input();
for(re int i=;i<=n;++i)
if(!id[i])
tarjan(i);
build();
solve();
return ;
}

Tarjan算法初探(2):缩点的更多相关文章

  1. Tarjan算法初探(3):求割点与桥以及双连通分量

    接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...

  2. Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量

    在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...

  3. tarjan算法求scc & 缩点

    前置知识 图的遍历(dfs) 强连通&强连通分量 对于有向图G中的任意两个顶点u和v存在u->v的一条路径,同时也存在v->u的路径,我们则称这两个顶点强连通.以此类推,强连通分量 ...

  4. poj1236 Network of Schools ,有向图求强连通分量(Tarjan算法),缩点

    题目链接: 点击打开链接 题意: 给定一个有向图,求: 1) 至少要选几个顶点.才干做到从这些顶点出发,能够到达所有顶点 2) 至少要加多少条边.才干使得从不论什么一个顶点出发,都能到达所有顶点   ...

  5. POJ 2762 Going from u to v or from v to u? Tarjan算法 学习例题

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17104   Accepted: 4594 Description In o ...

  6. 图之强连通--Tarjan算法

    强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components ...

  7. Tarjan算法 求 有向图的强连通分量

    百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...

  8. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  9. tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)

    这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...

随机推荐

  1. cacti 安装与 与不能显示图像故障解决方案

    on debian 7&8 apt-get install snmp snmpd apt-get install cacti cacti-spine apt-get install moreu ...

  2. 实用爬虫-02-爬虫真正使用代理 ip

    实用爬虫-02-爬虫真正使用代理 ip 因为这里呢,是实用爬虫,想要仔细学习一些基础的,可以去查看: Python 爬虫教程:https://www.cnblogs.com/xpwi/category ...

  3. OkHttp3源码详解(三) 拦截器-RetryAndFollowUpInterceptor

    最大恢复追逐次数: ; 处理的业务: 实例化StreamAllocation,初始化一个Socket连接对象,获取到输入/输出流()基于Okio 开启循环,执行下一个调用链(拦截器),等待返回结果(R ...

  4. “微软热爱Linux“ – 心声传遍中国

    去年十月微软CEO Satya Nadella在旧金山的活动中说 “微软热爱Linux(Microsoft loves Linux)”,这句话让诸多人感到惊喜.至此之后,您可以在众多Linux和开源的 ...

  5. fiddler抓包出现Tunnel to

    在抓包的时候,有时候会遇到很多的tunnel to,图标是一把锁的形状,如下图: connect是为了建立http tunnel,connect是http众多方法中的其中一种,它跟post.get.p ...

  6. 进程间通信——队列和管道(multiprocess.Queue、multiprocess.Pipe)

    进程: 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运 ...

  7. 《Python指南》学习笔记 一

    更新时间:2018-06-14 <Python指南>原文在这里.本篇笔记主要是划重点. Python 3.6.3 1.简单入门 1.1 编码 默认情况下,Python 源文件是 UTF-8 ...

  8. Python学习---django重点之视图函数

    django重点之视图函数 http请求中产生两个核心对象: http请求:HttpRequest对象,由Django自己创建 http响应:HttpResponse对象,由开发自己创建,必须返回一个 ...

  9. ZT 分智网博客 – 职场、面试技巧、职业规划

    http://blog.fenzhi.com/archives/5148.html 分智网博客 – 职场.面试技巧.职业规划 软件工程师职位薪酬最高的25家中国公司 作者: 分智网 日期: 2013 ...

  10. 在android工程中添加图片资源(转加)

    在Android工程中,每添加一个资源,就会在gen目录下的R.java中自动生成一个新的静态整型变量来指向这个资源.程序文件中调用资源的时候,先在R.java中找到变量名,然后根据变量值查找资源. ...