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 106. 从中序与后序遍历序列构造二叉树】解题报告
前往 中序,后序遍历构造二叉树, 中序,前序遍历构造二叉树 TreeNode* build(vector<int>& inorder, int l1, int r1, vector ...
- [WIP]laravel 入门
创建: 2019/06/20 安装 composer brew install composer laravel composer global require "laravel/i ...
- MATLAB求解非线性方程组
matlab中有专门的solve函数来解决方程组的(a-x)^2+(b-y)^2=e^2(C-x)^2+(D-y)^2=v^2已知a,b,c,d,e,v 值求解 X,Y 请问用 matlab 如何写, ...
- 读《JavaScript权威指南》笔记(二)
1.加号运算和比较运算符的区别 对于数字和字符串操作符来说,加号运算符和比较运算符的行为都有所不同,前者更偏爱字符串,如果它的其中一个操作数是字符串的话,则进行字符串连接操作.而比较运算符则更偏爱数字 ...
- android 手写万能adapter适配器
android开发中,我们离不开adapter,每个项目都有很多地方需要adapter,那么我们如何让自己少写adapter代码呢?那就是封装adapter,让我们的adapter成为万能的adapt ...
- JIRA reference
Workflow https://confluence.atlassian.com/adminjiracloud/configuring-workflow-schemes-776636598.html ...
- linux下生成随机密码
常见的简单的两种方法 1.openssl rand -base64 32 2.date | md5sum
- Helvetic Coding Contest 2016 online mirror D1
Description "The zombies are lurking outside. Waiting. Moaning. And when they come..." &qu ...
- springboot 参数校验详解
https://www.jianshu.com/p/89a675b7c900 在日常开发写rest接口时,接口参数校验这一部分是必须的,但是如果全部用代码去做,显得十分麻烦,spring也提供了这部分 ...
- 【Java密码学】用Java数字签名提供XML安全
简介 众所周知,XML在产品和项目开发中起着非常重要的作用.通过XML文档可以获取很多信息,还可以使用XML文件进行CRUD(增加.查询.更新和删除)操作.然而值得注意的是,我们如何确保XML中的数据 ...