题目

思路

不想写了,直接使用

没错,关键就在求第 \(k\) 小的路径

上述提到堆的做法,我们可以用 \(STL\) 的优先队列来实现

只不过常数有点大~~~

\(Code\)

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL; const int N = 1e5 + 5;
int n , k , h[N] , tot , cnt1 , cnt2;
LL a[N] , b[N]; struct edge{
int to , nxt , w;
}e[N << 1]; struct node{
int l , r;
LL d;
bool operator < (node c) const {return d > c.d;}
}; priority_queue<node> Q; inline void add(int x , int y , int z)
{
e[++tot].to = y;
e[tot].w = z;
e[tot].nxt = h[x];
h[x] = tot;
} inline void dfs(int x , int fa , int fl , LL D , int ad)
{
for(register int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa) continue;
D = D + 1LL * fl * e[i].w;
if (ad) a[++cnt1] = D;
else b[++cnt2] = -D;
dfs(v , x , -fl , D , ad ^ 1);
D = D - 1LL * fl * e[i].w;
}
} int main()
{
freopen("travel.in" , "r" , stdin);
freopen("travel.out" , "w" , stdout);
scanf("%d%d" , &n , &k);
int u , v , w;
for(register int i = 1; i < n; i++)
{
scanf("%d%d%d" , &u , &v , &w);
add(u , v , w) , add(v , u , w);
}
b[++cnt2] = 0;
dfs(1 , 0 , 1 , 0 , 1);
sort(a + 1 , a + cnt1 + 1) , sort(b + 1 , b + cnt2 + 1);
for(register int i = 1; i <= cnt1; i++) Q.push((node){i , 1 , a[i] + b[1]});
node now;
for(register int i = 1; i <= k; i++)
{
if (Q.size())
{
now = Q.top() , Q.pop();
if (i == k)
{
printf("%lld" , now.d);
return 0;
}
if (now.r + 1 <= cnt2) Q.push((node){now.l , now.r + 1 , a[now.l] + b[now.r + 1]});
}
else{
printf("Stupid Mike");
return 0;
}
}
}

对于此类问题,我们还有一个很经典的做法

二分答案,然后判断路径组合中比这个答案小的能不能达到 \(k\)

后半句可以再套个二分实现

\(Code\)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL; const int N = 1e5 + 5;
int n , k , h[N] , tot , cnt1 , cnt2;
LL a[N] , b[N]; struct edge{
int to , nxt , w;
}e[N << 1]; inline void add(int x , int y , int z)
{
e[++tot].to = y;
e[tot].w = z;
e[tot].nxt = h[x];
h[x] = tot;
} inline void dfs(int x , int fa , int fl , LL D , int ad)
{
for(register int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa) continue;
D = D + 1LL * fl * e[i].w;
if (ad) a[++cnt1] = D;
else b[++cnt2] = -D;
dfs(v , x , -fl , D , ad ^ 1);
D = D - 1LL * fl * e[i].w;
}
} inline int check(LL m)
{
int l , r , mid , res , sum = 0;
for(register int i = 1; i <= cnt1; i++)
{
l = 1 , r = cnt2 , res = 0;
while (l <= r)
{
mid = (l + r) >> 1;
if (b[mid] + a[i] <= m) res = mid , l = mid + 1;
else r = mid - 1;
}
sum += res;
}
return sum >= k;
} int main()
{
freopen("travel.in" , "r" , stdin);
freopen("travel.out" , "w" , stdout);
scanf("%d%d" , &n , &k);
int u , v , w;
for(register int i = 1; i < n; i++)
{
scanf("%d%d%d" , &u , &v , &w);
add(u , v , w) , add(v , u , w);
}
b[++cnt2] = 0;
dfs(1 , 0 , 1 , 0 , 1);
sort(a + 1 , a + cnt1 + 1) , sort(b + 1 , b + cnt2 + 1);
if ((LL)cnt1 * cnt2 < k)
{
printf("Stupid Mike");
return 0;
}
LL l = a[1] + b[1] , r = a[cnt1] + b[cnt2] , mid , res = l;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid)) res = mid , r = mid - 1;
else l = mid + 1;
}
printf("%lld" , res);
}

实际上这两做法各有优劣

如果要求前 \(k\) 的话显然用堆,它的过程本质上就是取出了前 \(k\) 的数

JZOJ 4320. 【NOIP2015模拟11.5】旅行的更多相关文章

  1. [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告

    题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...

  2. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  3. JZOJ 4298. 【NOIP2015模拟11.2晚】我的天

    4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...

  4. 【NOIP2015模拟11.5】JZOJ8月5日提高组T2 Lucas的数列

    [NOIP2015模拟11.5]JZOJ8月5日提高组T2 Lucas的数列 题目 PS:\(n*n*T*T<=10^{18}\)而不是\(10^1*8\) 题解 题意: 给出\(n\)个元素的 ...

  5. 【NOIP2015模拟11.5】JZOJ8月5日提高组T1 俄罗斯套娃

    [NOIP2015模拟11.5]JZOJ8月5日提高组T1 俄罗斯套娃 题目 题解 题意就是说 将1~\(n\)排列,问有多少种方案使得序列的逆序对个数小于\(k\) 很容易想到DP 设\(f[i][ ...

  6. 【NOIP2015模拟11.2晚】JZOJ8月4日提高组T2 我的天

    [NOIP2015模拟11.2晚]JZOJ8月4日提高组T2 我的天 题目 很久很以前,有一个古老的村庄--xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着 ...

  7. 【NOIP2015模拟11.4】JZOJ2020年8月6日提高组T2 最优交换

    [NOIP2015模拟11.4]JZOJ2020年8月6日提高组T2 最优交换 题目 题解 题意 有一个长度为\(n\)的正整数 最多可以进行\(k\)次操作 每次操作交换相邻两个位置上的数 问可以得 ...

  8. 【NOIP2015模拟11.4】JZOJ8月6日提高组T1 刷题计划

    [NOIP2015模拟11.4]JZOJ8月6日提高组T1 刷题计划 题目 题解 题意 有\(n\)道题,编号为1~\(n\) 给出\(m\)次操作 每次操作有3种类型 1 \(x\) 表示交了\(A ...

  9. 【NOIP2015模拟11.3】备用钥匙

    题目 你知道Just Odd Inventions社吗?这个公司的业务是"只不过是奇妙的发明(Just Odd Inventions)".这里简称为JOI社. JOI社有N名员工, ...

  10. JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝

    Description

随机推荐

  1. sublime text设置build system automatic提示no build system

    解决办法: 将: "selector": "source.asm" 改为: "selector": ["source.asm&qu ...

  2. python-面向对象属性的访问与self的理解

    属性访问 类属性与对象属性 在类中定义的名字,都是类的属性,细说的话,类有两种属性:数据属性和函数属性,可以通过__dict__访问属性的值,比如Person1.__dict__['student'] ...

  3. labuladong算法笔记总结

    动态规划解题套路框架 学习计划: 最长回文子序列 〇.必读文章 1.数据结构和算法学习指南(学习算法和刷题的框架思维) 了解数据结构的操作和遍历(迭代or递归) 从树刷起,结合框架思维,有利于理解(回 ...

  4. go操作Kfaka

    目录 1. Kafka介绍 1.1.1. Kafka是什么 1.1.2. Kafka的特点 1.1.3. 常用的场景 1.1.4. Kafka中包含以下基础概念 1.1.5. 消息 1.1.6. 消息 ...

  5. 彻底理解Python中的闭包和装饰器(上)

    什么是闭包 闭包(Closure)其实并不是Python独有的特性,很多语言都有对闭包的支持.(当然,因为Python是笔者除C/C++之外学习的第二门语言,所以也是第一次遇到闭包.)简而言之,闭包实 ...

  6. SpringBoot 自动装配的原理分析

    关于 SpringBoot 的自动装配功能,相信是每一个 Java 程序员天天都会用到的一个功能,但是它究竟是如何实现的呢?今天阿粉来带大家看一下. 自动装配案例 首先我们通过一个案例来看一下自动装配 ...

  7. python 之列表(list)处理

    列表(list) 创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可,一个列表中的数据类型可以各不相同,可以同时分别为整数.实数.字符串等基本类型,甚至是列表.元组.字典.集合以及其他自定 ...

  8. [OpenCV实战]5 基于深度学习的文本检测

    目录 1 网络加载 2 读取图像 3 前向传播 4 处理输出 3结果和代码 3.1结果 3.2 代码 参考 在这篇文章中,我们将逐字逐句地尝试找到图片中的单词!基于最近的一篇论文进行文字检测. EAS ...

  9. 基于Spark的均值漂移算法在网络舆情聚类中的应用

    知网链接 原文链接 张京坤,  王怡怡 软件导刊   2020年19卷第9期 页码:190-195 DOI:10.11907/rjdk.192529 出版日期:2020-9-15 摘 要: 为了改善网 ...

  10. 一问读懂Web3 架构

    最近看了一些Web3.0的文章,总结了一些个人的理解: Web3.0 通过区块链基础设施管理用户数据,重构用户和互联网平台之间的关系和交互,重新定义了互联网应用的架构方式和交互模式. Web 1.0 ...