Tarjan缩点+DAG图dp
题目背景
缩点+DP
题目描述
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
输入输出格式
输入格式:
第一行,n,m
第二行,n个整数,依次代表点权
第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
输出格式:
共一行,最大的点权之和。
输入输出样例
输入样例#1: 复制
2 2
1 1
1 2
2 1
输出样例#1: 复制
2
说明
n<=104,m<=105,|点权|<=1000 算法:Tarjan缩点+DAGdp`
如题,DAG图dp有一个很显然的思路--拓扑排序
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 100007;
int vul[maxn];
struct node{
int v,next;
}edge[maxn*5],edge1[maxn*5];
int head1[maxn],num1;
int head[maxn],num;
void add_edge(int u,int v) {
edge[++num].v=v;edge[num].next=head[u];head[u]=num;
}
void add_edge1(int u,int v) {
edge1[++num1].v=v;edge1[num1].next=head1[u];head1[u]=num1;
}
int n,m,cnt =0,dfn[maxn],low[maxn];bool vis[maxn];
int stack[maxn],top=0;
int vulue[maxn],sum,belong[maxn];
void tarjan(int x) {
low[x]=dfn[x]=++cnt;stack[++top]=x;
vis[x]=1;
for(int i=head[x];i;i=edge[i].next) {
int v=edge[i].v;
if(vis[v]) {
low[x]=std::min(low[x],dfn[v]);
}
else if(!dfn[v]){
tarjan(v);
low[x]=std::min(low[x],low[v]);
}
}
if(low[x]==dfn[x]) {
sum++;
belong[x]=sum;
vulue[sum]+=vul[x];
for(;stack[top]!=x;top--) {
belong[stack[top]]=sum;vis[stack[top]]=0;
vulue[sum]+=vul[stack[top]];
}
vis[x]=0; top--;
}
}
int rd[maxn];
int q[maxn],vull[maxn];
void top_sort(){
int h=1,tail=0;
for(int i=1;i<=sum;++i)
if(rd[i]==0) vull[i]=vulue[i],q[++tail]=i;
while(h<=tail) {
int x=q[h++];
for(int i=head1[x];i;i=edge1[i].next) {
int v=edge1[i].v;
if(rd[v]) {
vull[v]=std::max(vull[v],vull[x]+vulue[v]);
rd[v]--;
if(rd[v]==0) q[++tail]=v;
}
}
}
int ans=0;
for(int i=1;i<=sum;++i)
ans=std::max(ans,vull[i]);
printf("%d\n",ans);
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&vul[i]);
for(int a,b,i=1;i<=m;++i) {
scanf("%d%d",&a,&b);
add_edge(a,b);
}
for(int i=1;i<=n;++i)
if(!dfn[i])tarjan(i);
for(int i=1;i<=n;++i)
for(int j=head[i];j;j=edge[j].next) {
int v=edge[j].v;
if(belong[v]!=belong[i]) {
add_edge1(belong[i],belong[v]);
rd[belong[v]]++;
}
}
top_sort();
return 0;
}
Tarjan缩点+DAG图dp的更多相关文章
- [SDOI2010] 所驼门王的宝藏 [建图+tarjan缩点+DAG dp]
题面传送门: 传送门 思路: 看完题建模,容易得出是求单向图最长路径的问题 那么把这张图缩强联通分量,再在DAG上面DP即可 然而 这道题的建图实际上才是真正的考点 如果对于每一个点都直接连边到它所有 ...
- 洛谷 P2656 (缩点 + DAG图上DP)
### 洛谷 P2656 题目链接 ### 题目大意: 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖 ...
- bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...
- BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]
方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...
- BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】
题目 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G ...
- [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)
题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...
- UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)
题意:给定一个有向图,求出一个最大的结点集,这个节点集中的随意两个点之间至少一个能到达还有一个点. 思路:假设一个点在这个节点集中,那么它所在的强连通分量中的点一定所有在这个节点集中,反之亦然, 求出 ...
- 【Luogu】P3387缩点(Tarjan缩点+深搜DP)
题没什么好说的,因为是模板题.求值我用的是dfs. 不能直接在原图上dfs,因为原图上有环的话会发生一些滑稽的事情.所以我们要用Tarjan缩点.因为此题点权全为正,所以如果在图上走一个环当然可以全走 ...
- poj2186Popular Cows+tarjan缩点+建图
传送门: 题意: 给出m条关系,表示n个牛中的崇拜关系,这些关系满足传递性.问被所有牛崇拜的牛有几头: 思路: 先利用tarjan缩点,同一个点中的牛肯定就是等价的了,建立新的图,找出其中出度为0的点 ...
随机推荐
- 通用的前端js代码
1.判断是否移动设备的浏览器,是否允许触摸事件.(响应式网页) if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i. ...
- Selenium WebDriver- 使用Frame中的HTML源码内容操作Frame
#encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...
- Selenium WebDriver-判断页面中某一元素是否可操作
driver.get("http://127.0.0.1/test_enable.html") i1=driver.find_element_by_id("input1& ...
- 06-python进阶-多线程下载器练手
我们需要用python 写一个多线程的下载器 我们要先获取这个文件的大小 然后将其分片 然后启动多线程 分别去下载 然后将其拼接起来 #!/usr/bin/env python#coding:utf- ...
- 对python的想法
作为计算机专业的学生,在编程语言之余,我认为掌握一门脚本语言是很必要的.尤其是现在在数据分析,AI,机器学习等各个方面都大放异彩的python.相比于之前接触过的Java,C,C++乃至于php等语言 ...
- iOS学习笔记34-加速计和陀螺仪
一.CoreMotion框架介绍 我们知道有一些iOS的应用,会有一些特殊的要求,比如: 电子罗盘指南针之类的应用:让我们知道方向. 运动类型软件:让我们知道我们跑步多少公里. 社交软件中的摇一摇功能 ...
- [LOJ#526]「LibreOJ β Round #4」子集
[LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...
- openstack是什么?能干什么?
openstack是什么?能干什么?涉及的初衷是什么?由什么来组成?刚接触openstack,说openstack不是一个软件,而是由多个组件进行组合,这是一个更深层次的理解,当我们看到dashboa ...
- mybatis学习(十)——缓存介绍
与Hibernate一样,MyBatis 也提供了一级缓存和二级缓存的支持. 1.一级缓存:(本地缓存)SqlSession级别的缓存,默认一直开启的 , 与数据库同一次会话期间的数据会放到本地缓存中 ...
- tp90和tp99是指什么性能指标
原文: https://www.zhihu.com/question/41110088 https://www.google.com.hk/#safe=strict&q=tp50+tp90 T ...