[模板][Luogu3387] 缩点 - Tarjan, 拓扑+DP
Description
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
Input&Output
Input
第一行,n,m
第二行,n个整数,依次代表点权
第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
Output
共一行,最大的点权之和。
Sample
Input
2 2
1 1
1 2
2 1
Output
2
Solution
对于一个联通块,一定是经过其中所有点是最优的,所以我们可以缩点,新的点权是联通块内的点权和。
缩点后会得到一个DAG,此时一定是从入度为零的点走到出度为零的点最优,证明略。所以记录一下拓扑序,再做DP即可。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#define maxe 100005
#define maxn 10005
using namespace std;
struct edge{
int to,nxt;
}e[maxe];
struct cedge{
int to,nxt;
}ce[maxe];
int edgenum,cedgenum,lnk[maxn],clnk[maxn],k[maxn],a,b,n,m;
int dfn[maxn],low[maxn],dgr[maxn],cnt,num,blk[maxn],sz[maxn];
int f[maxn];
int hd=0,tl=1,q[maxn];
bool vis[maxn];
stack<int> st;
void add(int bgn,int end)
{
e[++edgenum].to=end;
e[edgenum].nxt=lnk[bgn];
lnk[bgn]=edgenum;
}
void c_add(int bgn,int end)
{
ce[++cedgenum].to=end;
ce[cedgenum].nxt=clnk[bgn];
clnk[bgn]=cedgenum;
dgr[end]++;
}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
vis[x]=1;st.push(x);
for(int p=lnk[x];p;p=e[p].nxt){
int y=e[p].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(vis[y])
low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]){
int now;
num++;
do{
now=st.top();st.pop();
vis[now]=0;
blk[now]=num;
}while(now!=x);
}
}
void toposort()
{
for(int i=1;i<=num;++i){
f[i]=sz[i];
if(!dgr[i])q[tl++]=i;
}
while(++hd<tl){
int u=q[hd];
for(int p=clnk[u];p;p=ce[p].nxt){
int y=ce[p].to;
if(!--dgr[y])q[tl++]=y;
}
}
}
void solve()
{
hd=0;
while(++hd<tl){
int u=q[hd];
for(int p=clnk[u];p;p=ce[p].nxt){
int y=ce[p].to;
f[y]=max(f[y],f[u]+sz[y]);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&k[i]);
for(int i=1;i<=m;++i)
scanf("%d%d",&a,&b),add(a,b);
for(int i=1;i<=n;++i)
if(!dfn[i])tarjan(i);
for(int i=1;i<=n;++i){
sz[blk[i]]+=k[i];
for(int p=lnk[i];p;p=e[p].nxt){
int y=e[p].to;
if(blk[i]!=blk[y])c_add(blk[i],blk[y]);
}
}
toposort();
solve();
int maxans=0;
for(int i=1;i<=num;++i)
maxans=max(maxans,f[i]);
printf("%d\n",maxans);
return 0;
}
[模板][Luogu3387] 缩点 - Tarjan, 拓扑+DP的更多相关文章
- P3387缩点(tarjan+拓扑排序+线性dp)
题目描述 给定一个 n个点 m 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 输入 ...
- P3387 【模板】缩点 tarjan
虽说是模板题,但是竟然中间有dp的部分...先tarjan缩点,重新建图.然后记忆化搜索,搜索dag中的最小环. 题干: 题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值, ...
- 【模板】缩点(tarjan,DAG上DP)
题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...
- 【模板】缩点 tarjan+dp
题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...
- 【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)
Luogu P3387 强连通分量的定义如下: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶 ...
- bzoj 2208: [Jsoi2010]连通数【tarjan+拓扑+dp】
我总觉得枚举点bfs也行-- tarjan缩点,记一下每个scc的size,bitset压一下scc里的点,然后按拓扑倒序向上合并到达状态,然后加ans的时候记得乘size #include<i ...
- BZOJ 1093 强连通缩点+DAG拓扑DP
缩点后在一个DAG上求最长点权链 和方案数 注意转移条件和转移状态 if (nowmaxn[x] > nowmaxn[v]) { ans[v] = ans[x]; nowmaxn[v] = no ...
- luogu P3387 【模板】缩点_拓扑排序
还是很好些的. Code: #include <stack> #include <cstdio> #include <algorithm> #include < ...
- 【tarjan 拓扑排序 dp】bzoj1093: [ZJOI2007]最大半连通子图
思维难度不大,关键考代码实现能力.一些细节还是很妙的. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于 ...
随机推荐
- java语言与jvm虚拟机简介
一.java语言 1.1 支持面向对象编程oop 强调支持,因为java同样可以面向过程编程. oop的三大特性是:封装.继承.多态. 封装主要针对成员变量而言,oop的思想要求成员变量均为私有,不应 ...
- Java 类文件结构
Java 诞生之时有句著名的宣传口号"Write Once, Run Anywhere.".但是,Java 语言本身不具备跨平台的能力,而是 JVM 提供了跨平台的能力. 事实上, ...
- spring-mvc 集成 activeMq 常见问题 + 解决方案 (仅供参考)
最近整合 spring-mvc 和 activeMq ,出现了几个异常,我把他记录下来,具体的原理分析我就不太会写了,只把详细情况和解决方案给出来,希望对各位老铁有所帮助! 问题1:缺少log4j的配 ...
- 用disabled属性修饰a标签,a标签仍然能点击
1.不知道各位同学有没有遇到跟我相同的问题,就是用jQuery操作a标签disabled的,来控制重复提交表单 做过开发的都知道,表单验证重复提交,包含前端和后端,两方面的控制.前端控制使我们常用的手 ...
- python变量定义和定义规范
变量定义的规则: 变量名只能是 字母.数字或下划线的任意组合 变量名的第一个字符不能是数字 以下关键字不能声明为变量名['and', 'as', 'assert', 'break', 'class', ...
- Maven-05:插件目标
在学习插件和生命周期的绑定关系之前,必须先了解插件目标(plugin goal). 我们知道,Maven的核心仅仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的构件形式存在,因此Mav ...
- poj 2681 字符串
http://poj.org/problem?id=2681 给你任意长度的字符串,找出两串字符中不相同的字符个数(总数) #include<string> #include<cst ...
- [poj2002]Squares_hash
Squares poj-2002 题目大意:在笛卡尔坐标系中给出n个点,求这些点可以构成多少个正方形. 注释:$1\le n\le 10^3$,$-2\cdot 10^3\le x , y\le 2\ ...
- 关于php日期前置是否有0
例如:2018-01-04,这个日期和月份前置是有0 如果不想有0,date( 'y-n-j',time() ):默认的是date( 'y-m-d',time() ),这个日期和月份前置是有0. da ...
- Maven安装配置【WIN10】
环境 WIN10 Maven 3.5.3 下载 下载地址:https://maven.apache.org/download.cgi 安装配置 选择好路径后一路 next 默认,安装完成. 环境变量设 ...