[模板][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,即对于 ...
随机推荐
- Git分支(2/5) -- Fast Forward 合并
快捷操作: 切换并创建分支: git checkout -b 分支名. git checkout -b some-change 然后我打开某个文件(index.html)修改一下标题. Commit之 ...
- 《Linux命令行与shell脚本编程大全》- 读书笔记2 - 更多的bash shell命令
更多的bash shell命令 想检测进程,需要熟悉ps命令的用法.ps命令好比工具中的瑞士军刀,它能输出运行在系统上的所有程序的许多信息.默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户 ...
- poj-1146 ID codes
Description It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In or ...
- oracle session数激增排查过程
我们的生产系统使用的是oracle 11G RAC,昨天突然收到微信告警通知session数达到450个,平时的session数在200个左右. select username,status,mach ...
- WEBLOGIC 11G (10.3.6) windows PSU 升级10.3.6.0.171017(Java 反序列化漏洞升级)
10.3.6版本的weblogic需要补丁到10.3.6.0.171017(2017年10月份的补丁,Java 反序列化漏洞升级),oracle官方建议至少打上2017年10月份补丁. 一.查看版本 ...
- Algorithm --> 全排列
1.算法简述 简单地说:全排列就是从第一个数字起每个数分别与它后面的数字交换. E.g:E = (a , b , c),则 prem(E)= a.perm(b,c)+ b.perm(a,c)+ c.p ...
- ElasticSearch之 控制相关度原理讲解
控制相关度 相关度评分背后的理论 如何计算评分的 Lucene 使用布尔模型(Boolean model) 查找匹配文档 并主要的借鉴了 词频/逆向文档频率(term frequency/invers ...
- Android Service基础
Service Service 是一个组件,用来执行长时间的后台操作,不提供用户界面. 另一个应用组件可以启动一个Service,它将持续地在后台运行,即便是用户转移到另一个应用它也不会停止. 另外, ...
- Idea 调试代码
---恢复内容开始--- set DEBUG_PORT=8787 set JAVA_DEBUG=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,addr ...
- linux No space left on device 由索引节点(inode)爆满引发500问题
inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取 ...