背景

今天\(loj\)挂了,于是就有了闲情雅致来刷\(luogu\)

题面

洛谷P3387 【模板】缩点传送门

题意

给定一个\(n\)个点\(m\)条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

思路

~~点击获得更好的阅读体验~~

\(Kosaraju\)缩点+记忆化搜索

什么是\(Kosaraju\)缩点?

与\(Tarjan\)缩点的时间复杂度差不多,都是\(O(n+m)\)。

其主要思想就是\(dfs\)两次。

核心代码如下:

void dfs_1(int x){
vis[x]=1;
for(int i=fir[x];i;i=nxt[i]){
if(vis[son[i]]==0) dfs_1(son[i]);
}
d[++t]=x;
}
void dfs_2(int x){
vis[x]=t;
s[t]++;
for(int i=fir2[x];i;i=nxt2[i]){
if(vis[son2[i]]==0) dfs_2(son2[i]);
}
}
void Kosaraju(){
t=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
if(vis[i]==0) dfs_1(i);
} memset(vis,0,sizeof(vis));t=0;
for(int i=n;i>=1;i--){
if(vis[d[i]]==0) t++,dfs_2(d[i]);
}
}

当然,我认为\(Kosaraju\)有一定的缺点,比如说要建反边。

具体\(Kosaraju\)算法的介绍戳这里

什么是记忆化搜索

记忆化搜索(Memory search)心理学是指搜索信息的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。

——百度百科

其实说白了就是\(dp\)的进阶。多了一个搜索。。。

只不过在\(dfs\)时开了个数组存储了当前的状态,以便以后搜索需要。

关于这道题

那么这道题就愉快的解决了。。。

思路如下:

为什么有这丑陋无比的水印

CODE:(PS:请忽略边权)

#include<algorithm>
#include<bitset>
#include<complex>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<iterator>
#include<limits>
#include<list>
#include<locale>
#include<map>
#include<memory>
#include<new>
#include<numeric>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<typeinfo>
#include<utility>
#include<valarray>
#include<vector>
#include<cctype>
#include<cerrno>
#include<cfloat>
#include<ciso646>
#include<climits>
#include<clocale>
#include<cmath>
#include<csetjmp>
#include<csignal>
#include<cstdarg>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#define E 200010
using namespace std;//丑陋无比的头文件
inline int read(){
int res=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
return res*f;
}//丑陋无比的读优
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x<10) putchar(x+'0');
else{
write(x/10);
putchar(x%10+'0');
}
}//丑陋无比的输优
int n,m,a[E];
int fir[E],nxt[E],w[E],son[E],tot;
int vis[E],d[E],top,f[E],ans;
int fir2[E],nxt2[E],w2[E],son2[E],tot2;
void add(int x,int y,int z){
++tot;
nxt[tot]=fir[x];
fir[x]=tot;
son[tot]=y;
w[tot]=z;
}//建正边
void add2(int x,int y,int z){
++tot2;
nxt2[tot2]=fir2[x];
fir2[x]=tot2;
son2[tot2]=y;
w2[tot2]=z;
}//建反边
void dfs1(int x){//Kosaraju算法第一次dfs
vis[x]=1;
for(int i=fir[x];i;i=nxt[i]){//正向
int to=son[i];
if(!vis[to]) dfs1(to);
}
d[++top]=x;
}
void dfs2(int x){//Kosaraju算法第二次dfs
vis[x]=top;//标记第几个强连通分量
for(int i=fir2[x];i;i=nxt2[i]){//反向
int to=son2[i];
if(!vis[to]) dfs2(to);
}
}
void dp(int x){//记忆化搜索
if(f[x]!=0) return ;//记忆化体现
int ss=0;
f[x]=d[x];
for(int i=fir2[x];i;i=nxt2[i]){//使用新的DAG
int to=son2[i];
dp(to);
ss=max(ss,f[to]);//取最大值
}
f[x]+=ss;//别忘记加回去
}
int main(){
n=read();m=read();//读入
for(int i=1;i<=n;i++) a[i]=read();//读入
for(int i=1;i<=m;i++){
int x=read(),y=read();
add(x,y,1);//建正边
add2(y,x,1);//建反边
}
//Kosaraju Start
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));top=0;//清空
for(int i=1;i<=n;i++){
if(!vis[i]) dfs1(i);//dfs第一次(正向)
}
memset(vis,0,sizeof(vis));top=0;//清空
for(int i=n;i>=1;i--){
if(!vis[d[i]]) ++top,dfs2(d[i]);//dfs第二次(反向)
}
//Kosaraju End
memset(d,0,sizeof(d));//清空
for(int i=1;i<=n;i++){
d[vis[i]]+=a[i];//权值累计
}
memset(fir2,0,sizeof(fir2));tot2=0;//清空
for(int i=1;i<=n;i++){//重新建DAG
for(int j=fir[i];j;j=nxt[j]){
int to=son[j];
if(vis[i]!=vis[to]) add2(vis[i],vis[to],1);//需要两个不同的强连通分量
}
}
for(int i=1;i<=top;i++){//记忆化搜索
if(!f[i]){//记忆化
dp(i);
ans=max(ans,f[i]);//取最大值
}
}
write(ans);putchar('\n');//输出
return 0;//结束
}

洛谷P3387 【模板】缩点 题解的更多相关文章

  1. 洛谷 P3387 【模板】缩点 DAGdp学习记

    我们以洛谷P3387 [模板]缩点 来学习DAGdp 1.这道题的流程 //伪代码 for i->n if(i未被遍历) tarjan(i) 缩点() DAGdp() 完成 首先tarjan这部 ...

  2. tarjan缩点练习 洛谷P3387 【模板】缩点+poj 2186 Popular Cows

    缩点练习 洛谷 P3387 [模板]缩点 缩点 解题思路: 都说是模板了...先缩点把有环图转换成DAG 然后拓扑排序即可 #include <bits/stdc++.h> using n ...

  3. 洛谷P1783 海滩防御 分析+题解代码

    洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...

  4. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  5. 洛谷P4047 [JSOI2010]部落划分题解

    洛谷P4047 [JSOI2010]部落划分题解 题目描述 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落 ...

  6. 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)

    洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...

  7. 【AC自动机】洛谷三道模板题

    [题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...

  8. 洛谷10月月赛II题解

    [咻咻咻] (https://www.luogu.org/contestnew/show/11616) 令人窒息的洛谷月赛,即将参加NOIp的我竟然只会一道题(也可以说一道也不会),最终145的我只能 ...

  9. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

随机推荐

  1. Ubuntu 14.04 将一个sh文件制作成类似于windows下的可以双击执行的快捷方式

    # 创建文件 touch test.desktop # 在test.desktop中写入如下内容 [Desktop Entry] Version=1.0 Type=Application Termin ...

  2. pgm10

    这部分讨论 MAP 估计.从某个角度上来说,我们可以将这个问题转换成为前面讨论过的: 这样一来我们只需要将原先的 sum-product 换成 max-sum 即可.话虽这么说,我们还是看看 Koll ...

  3. 使用System.getProperty方法,如何配置JVM系统属性

    原创文章,欢迎转载,转载请注明出处! 很多时候我们需要在项目中读取外部属性文件,用到了System.getProperty("")方法.这个方法需要配置JVM系统属性,那么如何配置 ...

  4. 基于Spark Mllib的文本分类

    基于Spark Mllib的文本分类 文本分类是一个典型的机器学习问题,其主要目标是通过对已有语料库文本数据训练得到分类模型,进而对新文本进行类别标签的预测.这在很多领域都有现实的应用场景,如新闻网站 ...

  5. LJ 5月6日A组考试考试题解

    [题目] T1(L2837) 晚餐队列安排 [题面] 为了避免餐厅过分拥挤,FJ要求奶牛们分2批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想,所有第2批就餐的奶牛排在队尾,队伍的前半部分 ...

  6. 生成器 yield

    由于生成器的其中一种创建方式与列表推导式很相似,这里先说一下列表推导式. 列表推导式 列表推导式又叫列表生成式,官方叫做 list comprehension.顾名思义,这个是用来生成列表的. 用法: ...

  7. sort与qsort的区别与联系

    sort属于C++范畴,在algorithm头文件中,下面直奔主题,给大家一个清晰明了的认识.qsort有C,和C++两个版本. qsort的compare函数原型 //comp ,也就说,如果the ...

  8. python的面向对象-实例(对象)的相关知识、实例化

    1.对象就是实例,什么是实例 类运行的过程就是实例化的过程,实例化产生的结果就是产生了一个实例 class的牛逼之处就是不用手动的return,他会加载完函数之后,自动return  __init__ ...

  9. Java 调用 groovy 脚本文件,groovy 访问 MongoDB

    groovy 访问 MongoDB 示例: shell.groovy package db import com.gmongo.GMongoClient import com.mongodb.Basi ...

  10. 并查集:POJ 1182 食物链 复习

    #include <iostream> #include <algorithm> #include <cstring> #include <cstdlib&g ...