Tarjan算法初探(2):缩点
接上一节 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):缩点的更多相关文章
- Tarjan算法初探(3):求割点与桥以及双连通分量
接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...
- Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量
在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...
- tarjan算法求scc & 缩点
前置知识 图的遍历(dfs) 强连通&强连通分量 对于有向图G中的任意两个顶点u和v存在u->v的一条路径,同时也存在v->u的路径,我们则称这两个顶点强连通.以此类推,强连通分量 ...
- poj1236 Network of Schools ,有向图求强连通分量(Tarjan算法),缩点
题目链接: 点击打开链接 题意: 给定一个有向图,求: 1) 至少要选几个顶点.才干做到从这些顶点出发,能够到达所有顶点 2) 至少要加多少条边.才干使得从不论什么一个顶点出发,都能到达所有顶点 ...
- 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 ...
- 图之强连通--Tarjan算法
强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components ...
- Tarjan算法 求 有向图的强连通分量
百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)
这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...
随机推荐
- 【javascript】javascript设计模式mixin模式
概述: Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现.任意一个对象的全部或部分属性拷贝到另一个对象上. 一 .混合对象 二 .混合类
- 浏览器好玩的的 console.log
现在很多网站,你在访问他页面的时候, 你要查看 console 的话, 看到有文章介绍的,一定想知道是怎么展示来的吧 如 baidu 的 你懂的,其实很简单,代码如下, console 输出下就行 c ...
- Linux命令行bash批量重命名文件
本文介绍下,在linux下使用shell批量重命名文件的例子,有需要的朋友参考下吧. 在linux中,重命名文件名,需要用到mv命令.如果需要批量重命名名一批文件,就需要写bash脚本或命令行了. 例 ...
- Centos7 下安装Apache2 + MySQL + PHP7
Apache 1.安装Apache yum install httpd 2.设置服务器开机自动启动Apache systemctl enable httpd.service 若要验证是否自动启动可在重 ...
- Android BitmapFactory.Options
public Bitmap inBitmap 如果设置,解码选项“对象的方法,采取将尝试重用这个位图加载内容时. public int inDensity 使用的位图的象素密度. public boo ...
- Android 虚拟多开系列二——技术原理
目录 Android虚拟多开应用有哪些? Android虚拟多开应用技术原理有哪几类? Android虚拟多开需求分析 反虚拟多开技术 ...
- hibernate对象的三种状态及转换
一.hibernate对象三种状态 Transient(瞬时状态):没有session管理,同时数据库没有对应记录 举例:new 出来的对象还没有被session管理,此时该对象处于Transient ...
- 排查在 Azure 中新建 Windows 虚拟机时遇到的经典部署问题
尝试创建新的 Azure 虚拟机 (VM) 时,遇到的常见错误是预配失败或分配失败. 当由于准备步骤不当,或者在从门户捕获映像期间选择了错误的设置而导致 OS 映像无法加载时,将发生预配失败. 当群集 ...
- C# 字符串中特定字符判断
/// <summary> /// 计算字符串中子串出现的次数 /// </summary> /// <param name="str">字符串 ...
- 使用公钥和私钥实现LINUX下免密登录
linux公钥私钥实现无密码登录 首先本地主机生成公约和私钥 # ssh-keygen /生成公钥和私钥 不要更改默认路径,中途不要输入密码,直接两次回车. 2. 将生成 ...