hiho一下 第三十八周 二分答案
题目链接:http://hihocoder.com/contest/hiho38/problem/1 ,挺难想的解题思路,好题。
按照提示的算法来:
我们需要找什么?
在这个题目中我们需要找的是路径最长边。比如存在一条路径{1, p[1], p[2], ... , p[j], T}, p = {p[1],p[2],...,p[j]] }, j < K,我们需要找的为 D(P) = Max{w(1, p[1]), w(p[j], T), Max{w(p[i], p[i+1]) | 1 <= i < j} }。则这道题的结果为找出所有从1到T的路径P',求的Min{D(P')}。由于给定的图存在环,所以要枚举出所有1到T的路径是很难的,因此我们需要换个角度去思考这个问题。
这道题结果有什么特殊性?
不妨假设答案为j,如果舰队满足j以上的索敌值,那么一定存在至少一条路径可以从1到T,并且路径数量小于K。如果舰队索敌值小于j,则在K条路径的条件下一定无法从1到T。否则j就不是最小值了。
则对于索敌值满足这样一个关系:
可以看出,j值刚好是是否存在路径的一个分界线。如果我们枚举一个j':
j'<j,无法到达boss点
j'>=j,一定可以到达boss点
则如何快速的找到这个分界线j,就是解决这道题目的关键。
不妨设f(x) = true(索敌值为x时,可以达到boss点), false(索敌值为x时,不能达到boss点)
二分枚举,设定枚举区间[L,R],满足f(L)=false, f(R)=true。每次取中间值Mid=(L+R)/2,若f(Mid)=true,令R=Mid;否则令L=Mid。
当L+1=R时,可以知道R即为我们需要寻找的j。
关于f(x)的求法:
可以用BFS来判断,这里要用一个数组deep[]记录每个结点的深度信息。所以访问到一个结点时,判断该结点是否能加入队列的条件有三个:该点未访问;到达该点后路径长度不超过k(用deep[]数组来判断);当前的索敌值x不小于这条边的索敌值w。
如果能在限制条件下到达boss的位置就返回true,否则返回false。
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF 1000005
const int maxn = + ;
struct Edge {
int v , w;
};
vector <Edge> e[maxn]; //邻接表来表示图
int vis[maxn] , deep[maxn];
bool check(int start , int j , int k , int end)
{ //用BFS来判断,起始点为start,j为最小索敌值,k为限制路径长度
memset(vis , , sizeof(vis));
queue <int> que;
que.push(start);
vis[start] = ;
deep[start] = ;
while(!que.empty()) {
int u = que.front();
que.pop();
for(int i = ; i < e[u].size() ; i++) {
int v = e[u][i].v;
int w = e[u][i].w;
if(!vis[v] && deep[u] < k && j >= w) { //三个条件
if(v == end)
return true;
vis[v] = ;
deep[v] = deep[u] + ;
que.push(v);
}
}
}
return false;
}
int binary_search(int l , int r , int k , int t)
{ //二分答案,区间为[l , r],限制路径长度k,终点为t
int m = (l + r) >> ;
while(l + != r) {
if(check( , m , k , t))
r = m;
else
l = m;
m = (l + r) >> ;
}
return r;
}
int main()
{
int n , m , k , t;
scanf("%d %d %d %d" , &n , &m , &k , &t);
while(m--) {
int u , v , w;
scanf("%d %d %d" , &u , &v , &w);
Edge tmp = {v , w};
e[u].push_back(tmp);
tmp.v = u;
e[v].push_back(tmp);
}
int res = binary_search( , INF , k , t);
printf("%d\n" , res);
return ;
}
hiho一下 第三十八周 二分答案的更多相关文章
- hiho一下 第三十九周 归并排序求逆序数
题目链接:http://hihocoder.com/contest/hiho39/problem/1 ,归并排序求逆序数. 其实这道题也是可以用树状数组来做的,不过数据都比较大,所以要离散化预处理一下 ...
- hihocoder第三十六周 二分查找
题目链接:http://hihocoder.com/contest/hiho36/problem/1 , 一个比较简单的二分. 算法: 由于数据量比较大,O(nlogn)无法通过,所以不能先排序再查找 ...
- hihoCoder hiho一下 第四十八周 题目1 : 拓扑排序·二
题意: 给定一个拓扑图,其中部分结点含有1个病毒,每个结点只要收到病毒就会立即往出边所能到达的点传播,病毒数可叠加,求所有结点的病毒数总和. 思路: 根据拓扑的特点,每个入度为0的点肯定不会再被传播病 ...
- hiho一下 第四十八周 拓扑排序·二【拓扑排序的应用 + 静态数组 + 拓扑排序算法的时间优化】
题目1 : 拓扑排序·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当 ...
- Java进阶(三十八)快速排序
Java进阶(三十八)快速排序 前言 有没有既不浪费空间又可以快一点的排序算法呢?那就是"快速排序"啦!光听这个名字是不是就觉得很高端呢. 假设我们现在对"6 1 2 7 ...
- 达拉草201771010105《面向对象程序设计(java)》第十八周学习总结
达拉草201771010105<面向对象程序设计(java)>第十八周学习总结 实验十八 总复习 实验时间 2018-12-30 1.实验目的与要求 (1) 综合掌握java基本程序结构 ...
- NeHe OpenGL教程 第三十八课:资源文件
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- SQL注入之Sqli-labs系列第三十八关、第三十九关,第四十关(堆叠注入)
0x1 堆叠注入讲解 (1)前言 国内有的称为堆查询注入,也有称之为堆叠注入.个人认为称之为堆叠注入更为准确.堆叠注入为攻击者提供了很多的攻击手段,通过添加一个新 的查询或者终止查询,可以达到修改数据 ...
- 微信小程序把玩(三十八)获取设备信息 API
原文:微信小程序把玩(三十八)获取设备信息 API 获取设备信息这里分为四种, 主要属性: 网络信息wx.getNetWorkType, 系统信息wx.getSystemInfo, 重力感应数据wx. ...
随机推荐
- 【leetcode 5. 最长回文子串】解题报告
方法一:中心扩展算法 解题思路:从左到右每一个字符都作为中心轴,然后逐渐往两边扩展,只要发现有不相等的字符,则确定了以该字符为轴的最长回文串,但需要考虑长度为奇数和偶数的不同情况的处理(长度为偶数时轴 ...
- [CentOS7] firewalld重启失败 Failed to start firewalld - dynamic firewall daemon.
错误信息: Failed to start firewalld - dynamic firewall daemon. 如图: 解决方法: 也就是kernel不支持现在的firewall防火墙的某些模块 ...
- 通过增删改查对比Array,Map,Set,Object的使用成本和实现方式
1.Array 和 Map 对比 { // array and map 增 查 改 删 let map = new Map(); let arr = []; // 增 map.set('a', 1); ...
- python之02数据类型学习-作业练习
题目: 购物车程序 salary = 5000 1. iphone6s 5800 2. mac book 9000 3. coffee 32 4. python book 80 5. bicyle 1 ...
- ubuntu 14.04安装octave,及其使用
从库安装: sudo apt-add-repository ppa:octave/stable sudo apt-get update sudo apt-get install octave 使用:以 ...
- 微信小程序 —— 微信小程序解析html富文本插件wxParse
下载并把wxParse放到小程序的目录中 github下载地址:https://github.com/icindy/wxParse 一.基本使用方法 1. Copy文件夹wxParse,把wxPars ...
- Leetcode初级算法(链表篇)
删除链表的倒数第N个节点 感觉自己对于链表的知识还是了解的不够深入,所以没有想到用双指针进行操作.我的想法是这样的,首先计算整个链表的长度,然后遍历到长度减去n的节点处,执行删除操作. 自己的代码: ...
- python_魔法方法(一):构造和析构
魔法方法总是被双下划线包围,例如:__init__() 魔法方法是面向对象的python的一切,它的魔力体现在总能在合适的时候调用. 先来介绍析构和构造的三个魔法方法: __init__():构造方法 ...
- 【ACM】棋盘覆盖 - 大数除
棋盘覆盖 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的 ...
- 031 Next Permutation 下一个排列
实现获取下一个排列函数,这个算法需要将数字重新排列成字典序中数字更大的排列.如果不存在更大的排列,则重新将数字排列成最小的排列(即升序排列).修改必须是原地的,不开辟额外的内存空间.这是一些例子,输入 ...