接上一节 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. LintCode2016年算法比赛----二叉树的所有路径

    二叉树的所有路径 题目描述 给定一棵二叉树,找从根节点到叶子节点的所有路径 样例 给出下面这课二叉树: 1 / \ 2 3 \ 5 所有根到叶子的路径为: [ "1->2->5& ...

  2. SPARK - Execute Framework

    Spark函数详解系列之RDD基本转换 https://www.cnblogs.com/MOBIN/p/5373256.html The  RDD provides low level API for ...

  3. Java 之集合框架 中(10)

    Map和HashMap Map接口: Map 提供了一种映射关系,其中的元素是以键值对(Key-Value)的形式 存储的,能够实现根据Key快速查找value Map中的键值对以Entry类型的对象 ...

  4. JAVA - JDK 1.8 API 帮助文档-中文版

    JAVA - JDK 1.8 API 帮助文档-中文版 百度云链接: https://pan.baidu.com/s/1_7FFadw1a6J0qTfx2FzqPQ 密码: 41n4

  5. Android画廊效果

    Android画廊效果 前言:Gallery是一个内部元素控件,可以水平滚动,并且可以把当前选择的子元素定位在它中心的布局组件:画廊Gallery一般用来显示可左右移动图片的列表(具体请看实例). 效 ...

  6. spring boot(1)-Hello World

    spring boot简介 spring boot是由spring官方推出的一个新框架,对spring进行了高度封装,是spring未来的发展方向.spring boot功用众多,其中最主要的功能就是 ...

  7. 2.java相对路径与绝对路径

    1.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:C:xyz/test.txt 代表了test.txt文件的绝对路径.http://www. ...

  8. C#中Equals和= =(等于号)的比较(转)

    一.           值类型的比较 对于值类型来说  两者比较的都是”内容”是否相同,即 值 是否一样,很显然此时两者是划等号的. 例: int i = 9; int j = 9; Console ...

  9. leetcode Ch5-Linked List

    一. 1. Remove Duplicates from Sorted List II class Solution { public: ListNode* deleteDuplicates(List ...

  10. Python 爬虫 获取标签下面的子标签

    thr_msgs = soup.find_all('div',class_=re.compile('msg')) for i in thr_msgs: print(i) first = i.selec ...