Tarjan+topsort(DP)【P3387】 [模板]缩点
Description
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
Input
第一行,n,m
第二行,n个整数,依次代表点权
第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
Output
共一行,最大的点权之和。
缩点+DP这是题目说的
先缩点,对于每一个联通块之间建边,这时得到一张\(DAG\)(有向无环图)
我们对其跑拓扑排序,然后开一个数组\(dis\)记录到达某个点的最大值.
对于那些入度为0的点,我们初始化其\(dis\)为其联通块的点权之和.
然后每次取\(max\)即可.
最终\(ans\)即为对到达每个点的\(dis\)取\(max\)。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#define R register
using namespace std;
const int gz=50008;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int head[gz],tot,val[gz],v[gz],h[gz],dis[gz],ins[gz],ans,n,m;
struct cod{int u,v;}edge[gz<<1],e[gz<<1];
inline void add(R int x,R int y)
{
edge[++tot].u=head[x];
edge[tot].v=y;
head[x]=tot;
}
inline void ado(R int x,R int y)
{
e[++tot].u=h[x];
e[tot].v=y;
h[x]=tot;
}
int dfn[gz],belong[gz],idx,low[gz],stk[gz],top,col;
bool inq[gz];
void tarjan(R int x)
{
low[x]=dfn[x]=++idx;
stk[++top]=x;inq[x]=true;
for(R int i=head[x];i;i=edge[i].u)
{
if(!dfn[edge[i].v])
{
tarjan(edge[i].v);
low[x]=min(low[x],low[edge[i].v]);
}
else if(inq[edge[i].v])
low[x]=min(low[x],dfn[edge[i].v]);
}
if(low[x]==dfn[x])
{
int now=-1;
col++;
while(now!=x)
{
now=stk[top--];
belong[now]=col;
inq[now]=false;
v[col]+=val[now];
}
}
}
inline void topsort()
{
top=0;
for(R int i=1;i<=col;i++)
if(!ins[i])stk[++top]=i,dis[i]=v[i];
while(top)
{
int u=stk[top--];
for(R int i=h[u];i;i=e[i].u)
{
ins[e[i].v]--;
dis[e[i].v]=max(dis[e[i].v],dis[u]+v[e[i].v]);
if(!ins[e[i].v])stk[++top]=e[i].v;
}
}
for(R int i=1;i<=col;i++)
ans=max(ans,dis[i]);
printf("%d\n",ans);
}
int main()
{
in(n),in(m);
for(R int i=1;i<=n;i++)in(val[i]);
for(R int i=1,x,y;i<=m;i++)
{
in(x),in(y);
add(x,y);
}
for(R int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
tot=0;
for(R int i=1;i<=n;i++)
for(R int j=head[i];j;j=edge[j].u)
if(belong[i]!=belong[edge[j].v])
{
ins[belong[edge[j].v]]++;
ado(belong[i],belong[edge[j].v]);
}
topsort();
}
Tarjan+topsort(DP)【P3387】 [模板]缩点的更多相关文章
- hdu:2089 ( 数位dp入门+模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 数位dp的模板题,统计一个区间内不含62的数字个数和不含4的数字个数,直接拿数位dp的板子敲就行 ...
- [模板][Luogu3387] 缩点 - Tarjan, 拓扑+DP
Description 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次 ...
- 【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)
Luogu P3387 强连通分量的定义如下: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶 ...
- 【UVA11324】 The Largest Clique (Tarjan+topsort/记忆化搜索)
UVA11324 The Largest Clique 题目描述 给你一张有向图 \(G\),求一个结点数最大的结点集,使得该结点集中的任意两个结点 \(u\) 和 \(v\) 满足:要么 \(u\) ...
- Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装
[洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...
- HDU5739 Fantasia 树形dp + 点双缩点
这个题当时打多校的时候有思路,但是代码能力差,没有写出来 事后看zimpha巨巨的题解,看了觉得基本差不多 核心思路:就是找出割点,然后变成森林,然后树形dp就可以搞了 关键就在重新构图上,缩完点以后 ...
- Tarjan求强连通分量,缩点,割点
Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...
- bzoj 4784: [Zjoi2017]仙人掌【tarjan+树形dp】
其实挺简单的但是没想出来---- 首先判断无解情况,即,一开始的图就不是仙人掌,使用tarjan判断如果一个点dfs下去有超过一个点比他早,则说明存在非简单环. 然后考虑dp,显然原图中已经属于某个简 ...
- bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】
一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp ...
随机推荐
- 【题解】APIO2013机器人
其实这题前前后后的思考时间加起来应该有两天之久了,dp状态,转移方式等等都还是比较好想,然而左看右看觉得spfa复杂度未免太爆炸……然后选择看了一篇题解,发现在多重优化之下,其实是可以过的…… 首先建 ...
- taotao用户登录springMVC拦截器的实现
在springMVC中写拦截器,只需要两步: 一.写 java 拦截器类,实现 interceptor 拦截器接口. 二.在 springMVC 的xml配置文件中,配置我们创建的拦截器对象及其拦截目 ...
- 第116讲 boost::algorithm::string之替换和删除
http://www.360doc.com/content/16/0523/18/29304643_561672752.shtml
- js实现快速排序的方法
因为面试面到了这个问题,所以写一下,加深印象,有两种方法 第一种是通过两个for循环,每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置,这个方法就是比较次数太多 ...
- KVO-基本使用方法-底层原理探究-自定义KVO-对容器类的监听
书读百变,其义自见! 将KVO形式以代码实现呈现,通俗易懂,更容易掌握 :GitHub -链接如果失效请自动搜索:https://github.com/henusjj/KVO_base 代码中有详 ...
- Asp.Net Core 基于QuartzNet任务管理系统(这是一篇用来水的随笔)
之前一直想搞个后台任务管理系统,零零散散的搞到现在,也算完成了. 废话不多说,进入正题. github地址:https://github.com/YANGKANG01/QuartzNetJob 一.项 ...
- js删除一个父元素下面的所有子元素
比如<div id="ok"><button tpye='button'>111111</button><p>22222</p ...
- LCD实验学习笔记(二):head.S
ARM加电后从0地址开始取指执行. 连接为bin文件时时,连接脚本lcd.lds指定将head.o放在开头,所以head.S就是系统起步的地方. head.S开头就是异常向量定义,0地址就是reset ...
- ZOJ 3599 K倍动态减法游戏
下面的文字辅助理解来自http://blog.csdn.net/tbl_123/article/details/24884861 博弈论中的 K倍动态减法游戏,难度较大,参看了好多资料才懵懂! 此题可 ...
- 1.flume概述
我们的web服务器等等每天会产生大量的日志,我们要把这些日志收集起来,移动到hadoop平台上进行分析. 那么如何移动这些数据呢?一种方法是通过shell cp到hadoop集群上,然后通过hdfs ...