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

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

因为可以重复经过点,所以一个点所在的强联通分量必定可以到达。所以直接缩点即可。

缩点之后,我们要让权值最大化,必须从入度为0的点开始搜。因为这是DAG,入度不为零的点的最后祖先必定是入度为零的点。由于这道题没有负数权值,从入度为零的结点开始走肯定是一个最好的选择。然后DAG上跑动归即可。

 #include <cstdio>
#include <cstring>
using namespace std; const int maxn=1e4+, maxm=1e5+; class Graph{
public:
//为什么用嵌套类,因为声明很烦。。并不是访问问题的原因。
//如果类的成员不是static的话,内部类是不知道获取哪个外部类对象的。。
//所以无论是把类放在里面还是外面,访问都有问题。
//另外,把private放在下面,应该是因为嵌套类类必须完全声明才能使用吧。。
//我也不大清楚。。先这么用着,以后再去翻c++ primer。
class Edge{
private:
Graph *belong;
public:
int v, to, next; //感觉这里还是不优雅。。
Edge(){}
Edge(Graph& g, int x, int y, int z){
belong=&g;
to=x, v=y, next=z;
}
Edge operator ++(){ //不能打引用!
*this=belong->edge[next]; //因为有自增运算,这个edge不能等同于图中的!
return *this;
}
int operator *(){
return to;
}
};
Graph(){}
void addedge(int x, int y, int v){
++cntedge;
edge[cntedge]=Edge(*this, y, v, fir[x]);
fir[x]=cntedge;
return;
}
Edge get_link(int x){ //这里改成begin较好
return edge[fir[x]];
}
private:
int cntedge, fir[maxn];
Edge edge[maxm];
}; int n, m, cnttime, cntscc;
int v[maxn], visit[maxn], time[maxn];
int scc[maxn], vofscc[maxn], in[maxn], ans[maxn];
Graph g, g_t, g_scc; void dfs(int now, int flag){
visit[now]=;
Graph::Edge e=g.get_link(now);
if (flag==) e=g_t.get_link(now);
int to=*e;
while (to){
if (!visit[to]) dfs(to, flag);
to=*(++e);
}
if (flag==){
++cnttime;
time[cnttime]=now;
}
if (flag==) {
scc[now]=cntscc;
vofscc[cntscc]+=v[now];
}
return;
} void dfs2(int x){
Graph::Edge e=g.get_link(x);
int to=*e;
visit[x]=;
while (to){
if (scc[to]!=scc[x]){
g_scc.addedge(scc[x], scc[to], v[scc[to]]);
++in[scc[to]];
}
if (!visit[to])
dfs2(to);
to=*(++e);
}
return;
} void dfs3(int x){
Graph::Edge e=g_scc.get_link(x);
int to=*e;
visit[x]=;
ans[x]=vofscc[x];
while (to){
if (!visit[to]) dfs3(to);
if (ans[to]+vofscc[x]>ans[x])
ans[x]=ans[to]+vofscc[x];
to=*(++e);
}
return;
} int main(){
scanf("%d%d", &n, &m);
for (int i=; i<=n; ++i)
scanf("%d", &v[i]);
int x, y;
for (int i=; i<=m; ++i){
scanf("%d%d", &x, &y);
g.addedge(x, y, );
g_t.addedge(y, x, );
} //建图
for (int i=; i<=n; ++i)
if (!visit[i]) dfs(i, ); //时间戳
memset(visit, , sizeof(visit));
for (int i=n; i>; --i){
if (!visit[time[i]]){
++cntscc;
dfs(time[i], );
}
} //求强联通分量
memset(visit, , sizeof(visit));
for (int i=; i<=n; ++i){
if (!visit[i]) dfs2(i);
} //缩点
for (int i=; i<=cntscc; ++i)
if (!in[i]) g_scc.addedge(, i, vofscc[i]); //超级源汇
memset(visit, , sizeof(visit));
dfs3(); //树形dp
printf("%d\n", ans[]);
return ;
}

洛谷P3387 缩点模板的更多相关文章

  1. 洛谷P3387缩点

    传送门 有向图.. 代码中有两种方法,拓扑排序和记忆化搜索 #include <iostream> #include <cstdio> #include <cstring ...

  2. 洛谷P3387 【模板】缩点 题解

    背景 今天\(loj\)挂了,于是就有了闲情雅致来刷\(luogu\) 题面 洛谷P3387 [模板]缩点传送门 题意 给定一个\(n\)个点\(m\)条边有向图,每个点有一个权值,求一条路径,使路径 ...

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

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

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

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

  5. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  6. 【洛谷4721】【模板】分治FFT(CDQ分治_NTT)

    题目: 洛谷 4721 分析: 我觉得这个 "分治 FFT " 不能算一种特殊的 FFT ,只是 CDQ 分治里套了个用 FFT (或 NTT)计算的过程,二者是并列关系而不是偏正 ...

  7. 【洛谷3865】 【模板】ST表(猫树)

    传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里

  8. 洛谷——P3387 【模板】缩点

    P3387 [模板]缩点 题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点, ...

  9. 【模板】缩点(Tarjan算法)/洛谷P3387

    题目链接 https://www.luogu.com.cn/problem/P3387 题目大意 给定一个 \(n\) 个点 \(m\) 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之 ...

随机推荐

  1. c语言代码风格

    简要:主要介绍了K&R风格和Allman(BSD)风格之间的缩进大小和大括号位置等区别 关于其它的代码风格,详见:Indent style - Wikipedia. 1.K&R sty ...

  2. Linux tar.gz 、zip、rar 解压 压缩命令

    tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...

  3. 使用kill命令终止进程shell脚本

    因有的程序使用kill才能结束掉进程,没有关闭脚本,以我司的服务为例,服务名叫asset-server服务,只有启动脚本,自编写关闭脚本,及重启动脚本. 关闭服务脚本. vim asset-shutd ...

  4. leetcode 162 Find Peak Element(二分法)

    A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ ...

  5. SQLite优化方法

    1.建表优化 SQLite的数据库本质文件读写操作,频繁操作打开和关闭是很耗时和浪费资源的: 优化方法事务机制: 这里要注意一点:事务的开启是要锁定DB的,其他对DB的写入操作都是无法成功的. db. ...

  6. FFmpeg 'scale' filter not present, cannot convert pixel formats.

    /*************************************************************************** * FFmpeg 'scale' filter ...

  7. poj2001Trie树模板

    #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #inc ...

  8. HEOI2017题解

    Day 1 : T1 : 期末考试 很水的一道题,但是自己搞了大半天过不了大样例. 最后还A了... 主要思想就是枚举最后一个完成的任务的时间 然后对两部分的代价分类讨论统计一下. (考试代码,略丑) ...

  9. bzoj 3514: GERALD07加强版 lct+可持久化线段树

    题目大意: N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 题解: 这道题考试的时候没想出来 于是便爆炸了 结果今天下午拿出昨天准备的题表准备做题的时候 题表里就有这题 ...

  10. 使用雅虎YUI Compressor压缩JS过程心得记录

    对待发布的项目进行测试时,发现js下载量比较大,从jquery的min版想到了压缩项目中的js文件.很简单的google之(在此,强调一下google的重要性),搜到一个叫做YUI Compresso ...