[MdOI R2] Odyssey 拓扑排序上DP
时间:2020-10-21
本文章向大家介绍[MdOI R2] Odyssey 拓扑排序上DP,主要包括[MdOI R2] Odyssey 拓扑排序上DP使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
[MdOI R2] Odyssey 拓扑排序上DP
题意
若正整数\(a,b\)满足
- 存在正整数\(c\),使得\(a \times b = c^k\)
则称为数对\((a,b)\)完美数对
有一个包含\(n\)个结点,\(m\)条边的有向无环图,这张图的每条边都有权值和长度两个属性。
如果一条路径\(P\)满足:
- \(P\)从起点开始经过依次为\(e_1,e_2,e_3...e_p\)这\(p\)条边,对于任意\(1 \leq i \leq p - 1\),\(e_i\)的权值和\(e_{i+1}\)的权值组成完美数对
则称为完美路径
找出图中最长的完美路径,输出长度之和
\[n\leq10^5\\
m \leq 2 \times10^5\\
k \leq10
\\w\leq10^5
\]
分析
首先处于一个有向无环图,自然希望通过\(dp\)来解决
先来处理给出的性质:
容易发现这里\(c\)是任意的,\(k\)是给定的,从唯一分解定理的角度考虑,我们只需要让每个质因子最终都是\(k\)的倍数即可。
所以处理方法就是对指数取模\(k\),要求剩下的指数能够满足,可以发现也是唯一对应的。
然后就考虑\(dp\)了,我们发现要到达当前边,必须通过前驱点的边的状态
\(dp[i][val]\)表示达到点\(i\),入边的边权为\(val\),所能得到的最大长度
\[dp[v][val] = max\{dp[u][inv(val)] + l\}
\]
然后在拓扑序上\(dp\)即可
代码
int n, m, k;
int indeg[maxn];
int ans;
unordered_map<int, int> mp[maxn];
int inv(int w) {
int res = 1;
for (int i = 2; i * i <= w; i++) {
int cnt = 0;
while (w % i == 0) w /= i, cnt++;
cnt %= k;
if (cnt) {
cnt = k - cnt;
while (cnt--) {
res *= i;
if (res > 100000) return -1;
}
}
}
if (w > 1) {
int cnt = k - 1;
while (cnt--) {
res *= w;
if (res > 100000) return -1;
}
}
return res;
}
int yu(int w) {
int res = 1;
for (int i = 2; i * i <= w; i++) {
int cnt = 0;
while (w % i == 0) w /= i, cnt++;
cnt %= k;
while (cnt--)
res *= i;
}
if (w > 1 && k != 1) return res * w;
else return res;
}
struct Edge {
int v;
int win, vin, val;
Edge(int _v, int _val, int _w) {
v = _v;
val = _val;
win = yu(_w);
vin = inv(_w);
}
};
vector<Edge> e[maxn];
void topo() {
queue<int> q;
for (int i = 1; i <= n; i++) if (!indeg[i]) q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < e[u].size(); i++) {
Edge y = e[u][i];
mp[y.v][y.vin] = max(mp[y.v][y.vin], mp[u][y.win] + y.val);
ans = max(ans, mp[y.v][y.vin]);
indeg[y.v]--;
if (!indeg[y.v]) q.push(y.v);
}
}
printf("%d", ans);
}
int main() {
n = readint();
m = readint();
k = readint();
for (int i = 1; i <= m; i++) {
int a = readint();
int b = readint();
int w = readint();
int v = readint();
e[a].push_back(Edge(b, v,w));
indeg[b]++;
}
topo();
}
原文地址:https://www.cnblogs.com/hznumqf/p/13855208.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android编程实现仿优酷圆盘旋转菜单效果的方法详解【附demo源码下载】
- Android绘制圆形百分比加载圈效果
- Android自定义view实现动态柱状图
- Kubernetes集群高可用&备份还原概述 | 知识分享月第三期直播回顾
- SpringCloud2020 学习笔记(一)springboot和springcloud技术选型以及版本选择
- SpringCloud2020 学习笔记(二)父工程搭建
- SpringCloud2020 学习笔记(三) cloud-api-commons通用模块搭建
- SpringCloud2020 学习笔记(四) cloud-provider-payment8001支付模块
- SpringCloud2020 学习笔记(五)cloud-consumer-order80 消费者订单模块
- SpringCloud2020 学习笔记(六)如何开启idea中的Run DashBoard or Services
- SpringCloud2020 学习笔记(七)cloud-eureka-server7001 EurekaServer服务端安装
- SpringCloud2020 学习笔记(八)cloud-provider-payment8001支付模块入驻eurekaServer注册中心
- SpringCloud2020 学习笔记(九)cloud-consumer-order80 消费者订单模块入驻eurekaServer注册中心
- SpringCloud2020 学习笔记(十)cloud-eureka-server7001 cloud-eureka-server7002 Eureka集群安装
- Python爬虫之抓取某东苹果手机评价