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的点 ...
随机推荐
- GoF23种设计模式之行为型模式之迭代器模式
一.概述 给定一种语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.二.适用性1.当访问一个聚合对象的内容而无需暴露它的内部表示的时候.2.当对聚合对象的多 ...
- OpenSSL version mismatch. Built against 1000105f, you have 10001060
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=732940 http://ftp.debian.org/debian/pool/main/o/ope ...
- Mysql之数据库用户操作
查看用户: select host,user from mysql.user; //mysql库中user表,host为主机地址,user为用户名 mysql> select host,user ...
- 03011_HttpServletRequest
1.HttpServletRequest概述 (1)我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代 ...
- JS实现——贪吃蛇
把以下代码保存成Snake.html文件,使用Google或360浏览器打开 <!DOCTYPE HTML> <html> <head> <meta char ...
- 为什么要使用数据库连接池?以及用法(DBUtils)
看代码, from flask import Flask from db import POOL import pymysql app = Flask(__name__) app.secret_key ...
- 忘记MySQL的root密码的解决方法
经常会有朋友或者同事问起,MySQL 的 root 密码忘了,不知道改怎么办. 其实解决方法很简单,下面是详细的操作步骤. (1)修改配置文件my.cnf,在配置文件[mysqld]下添加skip-g ...
- LiveScript 操作符
The LiveScript Book The LiveScript Book 操作符 数字 标准的数学操作符: 1.1 + 2 # => 32.3 - 4 # => -13.6 ...
- 轻量级的C++插件框架 - X3 C++ PluginFramework
X3 C++ PluginFramework 代号为X3的C++轻量级通用插件框架平台是一套通用的C++轻量级插件体系,没有使用MFC.ATL.COM.可在Windows和Linux下编译运行.应用程 ...
- [adb 学习篇] adb常用命令
https://testerhome.com/topics/2565 Android 常用 adb 命令总结 针对移动端 Android 的测试, adb 命令是很重要的一个点,必须将常用的 adb ...