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算法的功能很强大, 可以用来求解强连通分量, ...
随机推荐
- C++笔记(1)----此运算符函数的参数太多
在VS2015中定义了这样一个类: #include<iostream> #include<vector> #include<string> using names ...
- 空间分析开源库GEOS
History of GEOS GEOS中Geometry的结构 GEOS分析功能简介 1.History of GEOS JTS Topology Suite是Ma ...
- How to block a specific IP Address using UFW
How to block a specific IP Address using UFW The key to blocking a specific IP address with UFW is t ...
- C++ 多线程编程实例【2个线程模拟卖火车票的小程序】
原文:http://blog.csdn.net/chen825919148/article/details/7904219 核心提示:从网上搜集来的非常基础的C++多线程实例,刚入门的可以看看,希望能 ...
- 微信小程序-04-详解介绍.json 配置文件
致我自己:小程序开发不是简单一两天的事,一两天只能算是了解,有时候看多了会烦,感觉很熟悉了,其实只是对表面进行了解,对编程却知之甚少,小程序开发不是简单的改模板,一两天很多部分改模板可能都做不到,坚持 ...
- DrawerLayout使用
1 :DrawerLayout侧边栏用于实现如图所示的效果:
- 毕向东_Java基础视频教程第20天_IO流(15~17)
第20天-15-IO流(打印输出流) 打印输出流:PrintWriter与PrintStream 两者的区别:Since JDK 1.4 it's possible to specify the ch ...
- 利用Java反射实现JavaBean对象相同属性复制并初始化目标对象为空的属性的BeanUtils
有时遇到将数据传输对象转换成JSON串会将属性值为空的属性去掉,利用Java反射实现JavaBean对象数据传输对象的相同属性复制并初始化数据传输对象属性为空的属性,然后转换成JSON串 packag ...
- Python学习---列表/元组/字典/字符串/set集合/深浅拷贝1207【all】
1.列表 2.元组 3.字典 4.字符串 5.set集合 6.深浅拷贝
- 编码学习---代码OJ网站
代码OJ网站: https://leetcode-cn.com/accounts/login/