原题入口

PS:这个题数据是由Hany01大大出出来的 %%%

这个题显然是一道强联通+DAGdp的题 (题目背景有= =)

缩点的原因就是:不缩会一直在一个地方绕圈圈 而且不能进行后面的DAPdp 而且给你的所有点权全是正的

我在这用的是Tarjan(因为他发明算法太多了233)

这个dp方程比较容易找 令dp[u] 表示 缩点后 第u个强联通分量为起点的路径上点和的最大值

所以有 dp[u] = max{dp[v]} + val[u]  (这里v是指u出发可以到达的点)

由于是DAGdp 所以我们一开始要从入度为0的点出发 一直向下走 回溯的时候更改这个节点的dp值

下附程序(Tarjan讲解见程序):

#include <bits/stdc++.h>
#define For(i, l, r) for(int i = (l); i <= (int)(r); ++i)
#define Fordown(i, r, l) for(int i = (r); i >= (int)(l); --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std; inline int read() {
int x = , fh = ; char ch;
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -;
for (; isdigit(ch); ch = getchar()) x = (x<<) + (x<<) + (ch^'');
return x * fh;
} #include <stack>
const int N = 1e4+1e2, M = 1e5*+1e2; //点的范围和边的范围 开大点防止数据bug
struct edge {
int to[M], Next[M], Head[N], e;
void init() {Set(Head, ); e = ;}
}; //用链式前向星存边,访问更加迅速
edge G1, G2; //结构体便于多图 void add_edge (int u, int v, edge &G) { //引用G为了更新G
G.to[++G.e] = v;
G.Next[G.e] = G.Head[u];
G.Head[u] = G.e;
} //加入一条有向边 #define Travel(i, u, G) for(int i = G.Head[u]; i; i = G.Next[i])
//链式前向星的遍历方式 i表示在G图中,所有从u出发的边 (宏定义偷懒233)
int pre[N], lowlink[N], sccno[N], dfs_clock = , scc_cnt = ;
stack<int> S;
//Tarjan所需要的一些变量,时间戳dfs_clock,最早进入时间pre,能访问最远祖先lowlink
//强联通分量总数scc_cnt,每个点所属强联通分量编号sccno
int val[N], val1[N];
//val表示原图中的权值,val1表示缩点后每个强联通分量的权值
void Tarjan (int u) { //Tarjan主体(访问u)
pre[u] = lowlink[u] = ++dfs_clock; //第一次进入 把时间和最远到达祖先设为u
S.push(u); //把u放入栈中
Travel (i, u, G1) { //遍历原图从u开始的节点
int v = G1.to[i]; //取出到达的节点
if (!pre[v]) { //没有访问过
Tarjan (v); //递归向下继续搜
lowlink[u] = min(lowlink[u], lowlink[v]); //更新能到达最远祖先的值
} else if (!sccno[v]) //不是别的强联通分量中的点 且 已经访问过了(也就是存在了一条返祖边)
lowlink[u] = min(lowlink[u], pre[v]); //更新最远祖先(因为v在u之前被访问)证明有环
}
if (lowlink[u] == pre[u]) { //能到达的最远祖先就是自己
++scc_cnt; //将总数增加
for(;;) { //不断递归
int now = S.top(); S.pop(); //取出当前栈顶的数
sccno[now] = scc_cnt; //标记点的编号
val1[scc_cnt] += val[now]; //统计强联通分量的权值
if (now == u) break; //到了自己就停下来 不可能继续向上走了
}
}
} int in_deg[N]; //记录入度
int max_ans = ; //答案
int dp[N]; //dp数组
bool vis[N]; //标记是否到达
void dfs(int u) {
if (vis[u]) return;
vis[u] = true; //似乎不要也行 但好像更慢
dp[u] = val1[u]; //初始化标记为强联通得权值
Travel (i, u, G2) { //从缩点后的图开始遍历
int v = G2.to[i]; //取出到达点
dfs(v); //向下遍历
dp[u] = max(dp[u], dp[v] + val1[u]); //回溯时更新dp值
}
max_ans = max(max_ans, dp[u]); //更新答案
} int main() {
int n = read(), m = read();
G1.init(); G2.init();
For (i, , n)
val[i] = read();
while (m--) {
int u = read(), v = read();
add_edge (u, v, G1); //把边加入G1中
}
For (i, , n)
if (!pre[i]) Tarjan (i); //搜索强联通 For (i, , n)
Travel (j, i, G1) { //遍历所有的边
int v = G1.to[j];
if (sccno[i] == sccno[v]) continue; //如果在同一个强联通分量中就向下走
add_edge (sccno[i], sccno[v], G2); //把新边加入G2中
++in_deg[sccno[v]]; //增加v入度
} For (i, , scc_cnt)
if (!in_deg[i]) dfs(i); //搜索入度为0的点
printf ("%d\n", max_ans);
}

luogu【P3387】【模板】缩点的更多相关文章

  1. 【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)

    Luogu P3387 强连通分量的定义如下: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶 ...

  2. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  3. Luogu P2742 模板-二维凸包

    Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...

  4. luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

    luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...

  5. 解题报告+板子:luogu P3387 【模板】缩点

    题目链接:P3387 [模板]缩点 缩点板子,所谓\(dp\)就是拓扑排序(毕竟可以重走边),像\(SPFA\)一样松弛就好,就是重边极其烦人,还加了排序(绝对自己想的,然鹅拓扑的思路不是). 下面上 ...

  6. luogu P3387 【模板】缩点

    题目 好久没法博客了 这次就水个板子题目吧 tarjan缩点之后重新建图 而且边权应该都是正的(要不我怎么能这么轻松水过去) 在新图上记忆化一下就好了 f[i] 表示 开头选i这个点 的 路径最大值 ...

  7. LUOGU P3387 【模板】缩点 (缩点+DAG dp)

    解题思路 缩点后按拓扑排序跑一个dp. #include<iostream> #include<cstdio> #include<cstring> #include ...

  8. luogu P3387 【模板】缩点_拓扑排序

    还是很好些的. Code: #include <stack> #include <cstdio> #include <algorithm> #include < ...

  9. Tarjan+topsort(DP)【P3387】 [模板]缩点

    Description 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次 ...

  10. [模板](luogu P3387)縮點

    前言:對於這週的咕咕咕表示好像沒什麼好表示的,完全沒有靈感a......寫東西真的好難啊......於是又玩了半天鬼泣4???還挺好玩的 來源:題解 题目背景 缩点+DP 题目描述 给定一个n个点m条 ...

随机推荐

  1. create-react-app搭建的项目中添加bootstrap

    react-bootstrap是一个非常受欢迎的针对react封装过的bootstrap,它本身不包含css,所以也是需要使用bootstrap原生库. 在create-react-app建的项目目录 ...

  2. java 实现websocket的两种方式

    简单说明 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...

  3. 提高SQL查询效率

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  4. angular2 localStorage的使用

    最近从ng1  转ng2     相信 使用ng1的同学都知道 ngStorage 这个插件吧,  存储 本地数据 下面介绍一下 ng2 使用 localStorage 参考 github https ...

  5. for 循环中的 i 变量问题

    1:如何点击每一个 li 的时候 alert 输出其index? <ul id="test"> <li>111</li> <li>2 ...

  6. PowerDesigner 简单应用(转载)

    PowerDesigner是一款功能非常强大的建模工具软件,足以与Rose比肩,同样是当今最著名的建模软件之一.Rose是专攻UML对象模型的建模工具,之后才向数据库建模发展,而PowerDesign ...

  7. 使用tdload工具将本地数据导入到Teradata数据库中

    想把本地的数据文件(比如txt.csv)中的数据导入到Teradata虚拟机中的表中.既可以使用Teradata Assistant中的import功能,也可以使用fastload导入,前者的缺点是一 ...

  8. 第十八章 DjangoWeb开发框架

    第十八章 DjangoWeb开发框架 第一课 内容概要: 1.JS正则 -登录注册验证 2.组件 1.BootStrap -css -js 学习BootStrap规则 2.jQueryUI -css ...

  9. uva10976

    数学题. 1. 因为 1/k = 1/x +1/y 所以 1/k > 1/y 那么 y > k 2 . 因为 x >= y 所以 1/k - 1/y <= 1/y 那么 y & ...

  10. Apple 内购

    关于内购所需东西: 1.测试开发证书:需要打开in-app-purchase,绑定bundleid:com.aragon.TexasPoker 2.iTunes connect 里添加内购应用: 1& ...