1.USACO08JAN  Telephone Lines 题面

由于问的是最大值最小,所以二分加验证就好了

比较显然的,题干问的是第k+1长的路最短;

那么二分答案是正确的方向;

但是怎么验证?

我们可以将所有边权大于二分的答案的边视为边权是1,否则看成0;

然后从1~n跑最短路,如果答案大于二分的答案那么就不成立,否则成立;

这种思维比较重要,代码还是很简单的;

#include <bits/stdc++.h>
using namespace std;
int head[2000010],cnt;
class littlestar{
public:
int to;
int nxt;
int w;
void add(int u,int v,int gg){
nxt=head[u];
to=v;
w=gg;
head[u]=cnt;
}
}star[2000010];
int n,p,k;
int dis[100010],vis[100010];
bool SPFA(int x)
{
queue<int> q;
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
memset(vis,0,sizeof(vis));
q.push(1);
while(q.size()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=star[i].nxt){
int v=star[i].to;
if(dis[v]>dis[u]+(star[i].w>x)){
dis[v]=dis[u]+(star[i].w>x);
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
if(dis[n]<=k) return 1;
else{
return 0;
}
}
int main()
{
cin>>n>>p>>k;
for(int i=1;i<=p;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
star[++cnt].add(u,v,w);
star[++cnt].add(v,u,w);
}
int l=0,r=1000000;
while(l<r){
int mid=(l+r)/2;
if(SPFA(mid)){
r=mid;
}
else{
l=mid+1;
}
}
if(l==1000000) l=-1;
cout<<l<<endl;
}

2.[JLOI2011]飞行路线题面

这道题很上一道题不太一样,所求的是对于每种方案去掉前k大边后的最短路;

首先由于k很小,可以进行分层图;

第i层图表示目前已经删去了i条边的最短路;

对于点对(i,j)在任意层中边权是w;从第i层到第i+1层的边权是0;

然后堆优化+dijkstra就可以了;

#include <bits/stdc++.h>
using namespace std;
int head[5000010],cnt;
class littlestar{
public:
int to;
int nxt;
int w;
void add(int u,int v,int gg){
nxt=head[u];
to=v;
w=gg;
head[u]=cnt;
}
}star[5000010];
int n,p,k;
int dis[5000010],vis[5000010];
int S,T;
void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
priority_queue<pair<int,int> > q;
q.push(make_pair(0,S));
dis[S]=0;
while(q.size()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=star[i].nxt){
int v=star[i].to;
if(dis[v]>dis[u]+star[i].w){
dis[v]=dis[u]+star[i].w;
q.push(make_pair(-dis[v],v));
}
}
}
}
int main()
{
cin>>n>>p>>k;
cin>>S>>T;
++S;++T;
for(int i=1;i<=p;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
++u; ++v;
star[++cnt].add(u,v,w);
star[++cnt].add(v,u,w);
for(int j=0;j<k;j++){
star[++cnt].add((j+1)*n+u,(j+1)*n+v,w);
star[++cnt].add((j+1)*n+v,(j+1)*n+u,w);
star[++cnt].add(j*n+u,(j+1)*n+v,0);
star[++cnt].add(j*n+v,(j+1)*n+u,0);
}
}
for(int j=0;j<=k;j++){
star[++cnt].add(j*n+T,n*30+T,0);
}
dijkstra();
cout<<dis[n*30+T];
}

3.[BJWC2012]冻结

和上一道题思路一样,都是分层图,但连接第i层和第i+1层的边权不再是0,而是w/2;

#include <bits/stdc++.h>
using namespace std;
int head[5000010],cnt;
class littlestar{
public:
int to;
int nxt;
int w;
void add(int u,int v,int gg){
nxt=head[u];
to=v;
w=gg;
head[u]=cnt;
}
}star[5000010];
int n,p,k;
int dis[5000010],vis[5000010];
void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
priority_queue<pair<int,int> > q;
q.push(make_pair(0,1));
dis[1]=0;
while(q.size()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=star[i].nxt){
int v=star[i].to;
if(dis[v]>dis[u]+star[i].w){
dis[v]=dis[u]+star[i].w;
q.push(make_pair(-dis[v],v));
}
}
}
}
int main()
{
cin>>n>>p>>k;
for(int i=1;i<=p;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
star[++cnt].add(u,v,w);
star[++cnt].add(v,u,w);
for(int j=0;j<k;j++){
star[++cnt].add((j+1)*n+u,(j+1)*n+v,w);
star[++cnt].add((j+1)*n+v,(j+1)*n+u,w);
star[++cnt].add(j*n+u,(j+1)*n+v,w/2);
star[++cnt].add(j*n+v,(j+1)*n+u,w/2);
}
}
for(int j=0;j<=k;j++){
star[++cnt].add(j*n+n,n*30+1,0);
}
dijkstra();
cout<<dis[n*30+1];
}

4.[USACO09FEB]改造路Revamping Trails

思路重复,代码几乎一样,就不多说了;把这到题放到这里的原因是想告诉大家,USACO的题要好好做啊,很多省选题都来源于此;

#include <bits/stdc++.h>
using namespace std;
int head[5000010],cnt;
class littlestar{
public:
int to;
int nxt;
int w;
void add(int u,int v,int gg){
nxt=head[u];
to=v;
w=gg;
head[u]=cnt;
}
}star[5000010];
int n,p,k;
int dis[5000010],vis[5000010];
void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
priority_queue<pair<int,int> > q;
q.push(make_pair(0,1));
dis[1]=0;
while(q.size()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=star[i].nxt){
int v=star[i].to;
if(dis[v]>dis[u]+star[i].w){
dis[v]=dis[u]+star[i].w;
q.push(make_pair(-dis[v],v));
}
}
}
}
int main()
{
cin>>n>>p>>k;
for(int i=1;i<=p;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
star[++cnt].add(u,v,w);
star[++cnt].add(v,u,w);
for(int j=0;j<k;j++){
star[++cnt].add((j+1)*n+u,(j+1)*n+v,w);
star[++cnt].add((j+1)*n+v,(j+1)*n+u,w);
star[++cnt].add(j*n+u,(j+1)*n+v,0);
star[++cnt].add(j*n+v,(j+1)*n+u,0);
}
}
for(int j=0;j<=k;j++){
star[++cnt].add(j*n+n,n*30+1,0);
}
dijkstra();
cout<<dis[n*30+1];
}

有关最短路上的第k小/大值的总结的更多相关文章

  1. luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值

    ————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...

  2. poj2828(线段树查找序列第k小的值)

    题目链接:https://vjudge.net/problem/POJ-2828 题意:有n个人,依次给出这n个人进入队列时前面有多少人p[i],和它的权值v[i],求最终队列的权值序列. 思路:基本 ...

  3. MATLAB寻找数组前k个大值

    有时候我们需要寻找数组的前k个大值并按照顺序输出, 在C语言可以通过快速排序等算法,快速求得,这里用matlab写了一个比较简单实用的程序(适用于数组长度不是特别大的情况). function [va ...

  4. 求第 k 小:大元素

    #include<bits/stdc++.h> using namespace std; void swap_t(int a[],int i,int j) { int t=a[i]; a[ ...

  5. poj 3685 矩阵问题 查找第K小的值

    题意:N阶矩阵Aij= i2 + 100000 × i + j2 – 100000 × j + i × j,求第M小的元素. 思路:双重二分 考虑到,aij是跟着i递增的,所以i可以作为一个二分搜索 ...

  6. 算法---数组总结篇2——找丢失的数,找最大最小,前k大,第k小的数

    一.如何找出数组中丢失的数 题目描述:给定一个由n-1个整数组成的未排序的数组序列,其原始都是1到n中的不同的整数,请写出一个寻找数组序列中缺失整数的线性时间算法 方法1:累加求和 时间复杂度是O(N ...

  7. 树上第k小,可持久化线段树+倍增lca

    给定一颗树,树的每个结点都有权值, 有q个询问,每个询问是 u v k ,表示u到v路径上第k小的权值是多少. 每个结点所表示的线段树,是父亲结点的线段树添加该结点的权值之后形成的新的线段树 c[ro ...

  8. BZOJ 3065 带插入区间K小值(sag套线段树)

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 4696  Solved: 1527[Submit][Status][Di ...

  9. 刷题-力扣-230. 二叉搜索树中第K小的元素

    230. 二叉搜索树中第K小的元素 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a ...

随机推荐

  1. 2019南昌网络赛 J Distance on the tree 主席树+lca

    题意 给一颗树,每条边有边权,每次询问\(u\)到\(v\)的路径中有多少边的边权小于等于\(k​\) 分析 在树的每个点上建\(1​\)到\(i​\)的权值线段树,查询的时候同时跑\(u,v,lca ...

  2. 顺序表应用8:最大子段和之动态规划法(SDUT 3665)

    Problem Description 给定n(1<=n<=100000)个整数(可能为负数)组成的序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a ...

  3. 无法连接虚拟设备 ide1:0

    问题: 启动vmware之后,发现出现无法连接 ide 1:0. 网络查找之后,发现是之前挂载的iso镜像找不到了. 原因: 我把iso镜像放到其他位置. 解决: 指定iso文件的位置. 参考:htt ...

  4. 为什么还需要学习TypeScript

    开篇 TypeScript 是由 C#语言的创始人 Anders Hejlsberg 设计的一种编程语言,设计的初衷就是为了帮助 JavaScript 的开发人员能像类似高级语言c#,Java那样编写 ...

  5. 微信公众号实现无限制推送模板消息!可向指定openID群发

    微信认证的服务号才有推送模板消息接口所以本文需要在认证服务号的情况下学习 以上就是模板消息,只有文字和跳转链接,没有封面图.在服务号的后台添加功能插件-模板消息即可. 模板消息,都是在后台选择一个群发 ...

  6. CI集成Smarty的实现方式

    给新伙伴的忠告:不要去想着有多复杂,看一遍绝对就会弄了! 这样集成的目的是什么? 因为我使用过CI和smarty,所以我就按自己的理解讲一下:CI框架在控制器.models方面做的很好,但在多变的视图 ...

  7. Python中异常和JSON读写数据

    异常可以防止出现一些不友好的信息返回给用户,有助于提升程序的可用性,在java中通过try ... catch ... finally来处理异常,在Python中通过try ... except .. ...

  8. WorkStation 虚拟机迁移到 ESXi

    将Workstation的vmdk文件导入到Esxi. 提示如题错误提示. 无法打开磁盘 scsi0:0: 磁盘类型 7 不受支持或无效.请确保磁盘已导入. 在VMware Workstation,V ...

  9. JSTL标签(核心标准库)

    使用JSTL标签步骤 1) 导入jstl支持的jar包(标签背后隐藏的java代码) 注意:使用javaee5.0的项目自动导入jstl支持jar包 2)使用taglib指令导入标签库 <%@t ...

  10. linux添加用户所在群组

    etc目录下面有两个文件一个passwd一个grouppasswd里gid是主组,其他组是扩展组,扩展组在/etc/group里描述.useradd username如果不指定,默认创建一个与uid相 ...