洛谷P3387 缩点模板
给定一个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 缩点模板的更多相关文章
- 洛谷P3387缩点
传送门 有向图.. 代码中有两种方法,拓扑排序和记忆化搜索 #include <iostream> #include <cstdio> #include <cstring ...
- 洛谷P3387 【模板】缩点 题解
背景 今天\(loj\)挂了,于是就有了闲情雅致来刷\(luogu\) 题面 洛谷P3387 [模板]缩点传送门 题意 给定一个\(n\)个点\(m\)条边有向图,每个点有一个权值,求一条路径,使路径 ...
- 洛谷 P3387 【模板】缩点 DAGdp学习记
我们以洛谷P3387 [模板]缩点 来学习DAGdp 1.这道题的流程 //伪代码 for i->n if(i未被遍历) tarjan(i) 缩点() DAGdp() 完成 首先tarjan这部 ...
- tarjan缩点练习 洛谷P3387 【模板】缩点+poj 2186 Popular Cows
缩点练习 洛谷 P3387 [模板]缩点 缩点 解题思路: 都说是模板了...先缩点把有环图转换成DAG 然后拓扑排序即可 #include <bits/stdc++.h> using n ...
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- 【洛谷4721】【模板】分治FFT(CDQ分治_NTT)
题目: 洛谷 4721 分析: 我觉得这个 "分治 FFT " 不能算一种特殊的 FFT ,只是 CDQ 分治里套了个用 FFT (或 NTT)计算的过程,二者是并列关系而不是偏正 ...
- 【洛谷3865】 【模板】ST表(猫树)
传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里
- 洛谷——P3387 【模板】缩点
P3387 [模板]缩点 题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点, ...
- 【模板】缩点(Tarjan算法)/洛谷P3387
题目链接 https://www.luogu.com.cn/problem/P3387 题目大意 给定一个 \(n\) 个点 \(m\) 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之 ...
随机推荐
- windows下安装配置nginx
下载nginx-1.0.11.zip, 解压到到nginx目录下 D:\nginx\conf 修改conf下的nginx.conf文件, 默认是80端口,若该端口被占则可以修改 listen 8073 ...
- Java_JS_01_java调用js
二.资源帖 1.JAVA执行javascript方法 2.在Java中直接调用js代码 3.Java执行js脚本 4.Java 8 Nashorn 教程 5.Java 脚本引擎
- Git_学习_01_ 常用 Git 命令清单
我每天使用 Git ,但是很多命令记不住. 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令. 下面是我整理的常用 Git 命令清单.几个专用名词的译名如下 ...
- Java微信开发_Exception_03_errcode:48001 errmsg:api unauthorized hint
创建菜单时出现这个异常, 异常信息:errcode:48001 errmsg:api unauthorized hint 解读:调用的接口没有权限. 回去公众号后台一看,发现真的没有自定义菜单的权限, ...
- 关于MFC的DLL调用方法问题
参考资料: 一.dll导出方式: MFC的DLL函数导出方法有两种:一种是通过模块定义文件DEF文件:另一种是在导出函数前加_declspec(dllexport). 1.def文件方法: 只需要在E ...
- linux命令学习笔记(50):crontab命令
前一天学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,linux系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个 ...
- 本地未安装Oracle数据库,如何连接远程Oracle数据库
方法一:用Navicat Premium连接 注意,这里用的要是黄色的版本,而不是只针对Mysql的绿色版本 工具栏选择[工具]-[选项],点击[其他-OCI] 你会发现有个OCI librar ...
- ACM学习历程—51NOD1028 大数乘法V2(FFT)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1028 题目大意就是求两个大数的乘法. 但是用普通的大数乘法,这 ...
- log4net 使用
1. 代码中使用配置文件: log4net.Config.DOMConfigurator.Configure(new FileInfo("log4netConfig.xml")); ...
- poj 2000 Gold Coins(水题)
一.Description The king pays his loyal knight in gold coins. On the first day of his service, the kni ...