给定一个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. kaggle 欺诈信用卡预测——不平衡训练样本的处理方法 综合结论就是:随机森林+过采样(直接复制或者smote后,黑白比例1:3 or 1:1)效果比较好!记得在smote前一定要先做标准化!!!其实随机森林对特征是否标准化无感,但是svm和LR就非常非常关键了

    先看数据: 特征如下: Time Number of seconds elapsed between each transaction (over two days) numeric V1 No de ...

  2. Struts2 第一个入门小案例

    1.加载类库 2 配置web.xml文件 3.开发视图层 4.开发控制层Action 5.配置struts.xml 6.部署运行

  3. python-多线程(一)

    一.Python中的线程使用: Python中使用线程有两种方式:函数或者用类来包装线程对象. 1.  函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: ...

  4. 201621123014《JAVA程序设计》第2周学习总结

    1. 本周学习总结 引用数据类型:JAVA定义字符串实际上是创建字符串的引用,将引用指向需要的字符串. 字符串常量池:直接对引用赋值时,会先在字符串中搜索是否有这个对象,已有则不创建直接指向它. St ...

  5. (转)C协程实现的效率对比

    前段时间实现的C协程依赖栈传递参数,在开启优化时会导致错误,于是实现了一个ucontext的版本,但ucontext的切换效率太差了, 在我的机器上执行4000W次切换需要11秒左右,这达不到我的要求 ...

  6. 《Effective C++》学习笔记(一)

    1.const成员函数不能更改成员变量 #include <bits/stdc++.h> using namespace std; class CtextBlock { public: s ...

  7. Postgresql windows下安装过程

    1.下载前三个软件: 理论上安装Perl,TCL,Bison and Flex这三个插件 实际上安装ActiveState Perl,ActiveState tcl ,MinGW 因为MinGW包括了 ...

  8. 【C++ Primer 5th】Chapter 1

    1. 每个C++都包含至少一个函数,其中一个必须为main函数,且 main 函数的返回类型必须为 int. 2. 函数定义包括:返回类型,函数名,形参列表,函数体 3. main 函数返回值用来指示 ...

  9. python【事物 】【数据库锁】

    1.数据库事物 1. 什么是事务  事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一 ...

  10. Hadoop问题集锦

    1.Permission denied: user=root, access=WRITE, inode="/user":hdfs:supergroup 使用Spark进行处理的时候 ...