这道题目有两种解法:

1.将每个点视为一个二元组(x,p),表示从起点到x有p条路径免费,相当于构建了一张分层图,N*k个节点,P*k条边。在这张图上用优先队列优化的SPFA算法求解,注意这里的d数组存的不是最短路径,而是路径中边权最大的值,最终答案就是min(d[n][j]),0<=j<=k 。

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int N=1005,M=20005;
4 int head[N],to[M],w[M],nxt[M],tot;
5 int n,m,k,d[N][N];
6 bool v[N][N];
7 priority_queue< pair<int,pair<int,int> > > q;//加负值变为小根堆
8
9 void add(int x,int y,int z){
10 nxt[++tot]=head[x];
11 head[x]=tot;
12 to[tot]=y;
13 w[tot]=z;
14 }
15
16 int main(){
17 scanf("%d%d%d",&n,&m,&k);
18 for(int i=1;i<=m;i++){
19 int x,y,z;
20 scanf("%d%d%d",&x,&y,&z);
21 add(x,y,z);add(y,x,z);
22 }
23 memset(d,0x3f,sizeof(d));
24 d[1][0]=0;
25 q.push(make_pair(0,make_pair(1,0)));
26 while(q.size()){
27 int i=q.top().second.first,j=q.top().second.second;
28 q.pop();
29 if(v[i][j]) continue;
30 v[i][j]=true;
31 for(int e=head[i];e;e=nxt[e]){
32 int y=to[e],z=w[e];
33 if(d[y][j]>max(d[i][j],z)){//第一种状态转移
34 d[y][j]=max(d[i][j],z);
35 q.push(make_pair(-d[y][j],make_pair(y,j)));
36 }
37 if(j<k && d[y][j+1]>d[i][j]){//第二种状态转移
38 d[y][j+1]=d[i][j];
39 q.push(make_pair(-d[y][j+1],make_pair(y,j+1)));
40 }
41 }
42 }
43 int ans=0x3f3f3f3f;
44 for(int j=0;j<=k;j++) ans=min(ans,d[n][j]);
45 if(ans==0x3f3f3f3f) puts("-1");
46 else printf("%d\n",ans);
47 }

2.本题答案具有单调性,可以二分答案求解,转化为判定问题。

对于每个mid,将图中权值>mid的边看做1,权值<=mid的边看做0,然后求1到N的最短路是否不超过k。

对于这种只有0,1边权的图,可以用双端队列BFS求解最短路,0的话放在队头,1的话放在队尾。

调了好久...发现是模板打错了,不能加上if(v[y]) continue; 这样使y不能被进一步更新;而dijkstra可以,因为之前求过的已经是最短路径了,没必要再次更新。

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int N=1005,M=20005;
4 int head[N],to[M],w[M],nxt[M],tot;
5 int n,m,k,mx,ans,d[N];
6 bool v[N];
7 deque<int> q;
8
9 void add(int x,int y,int z){
10 nxt[++tot]=head[x];
11 head[x]=tot;
12 to[tot]=y;
13 w[tot]=z;
14 }
15
16 bool check(int mid){
17 memset(d,0x3f,sizeof(d));
18 memset(v,false,sizeof(v));
19 d[1]=0;v[1]=true;
20 q.push_back(1);
21 while(!q.empty()){
22 int x=q.front();q.pop_front();
23 v[x]=false;
24 for(int i=head[x];i;i=nxt[i]){
25 int y=to[i],z=w[i]>mid?1:0;
26 //if(v[y]) continue;注意加上这句是错误的
27 if(d[y]>d[x]+z){
28 d[y]=d[x]+z;
29 v[y]=true;
30 if(z==0) q.push_front(y);
31 else q.push_back(y);
32 }
33 }
34 }
35 return d[n]<=k;
36 }
37
38 int main(){
39 scanf("%d%d%d",&n,&m,&k);
40 for(int i=1;i<=m;i++){
41 int x,y,z;
42 scanf("%d%d%d",&x,&y,&z);
43 add(x,y,z);add(y,x,z);
44 }
45 int l=0,r=1000001;
46 while(l<r){
47 int mid=(l+r)>>1;
48 if(check(mid)) r=mid;
49 else l=mid+1;
50 }
51 if(l==1000001) puts("-1");
52 else printf("%d\n",l);
53 }

POJ3662 [USACO08JAN]Telephone Lines (二分答案/分层图求最短路)的更多相关文章

  1. poj-3662 Telephone Lines 二分答案+最短路

    链接:洛谷 POJ 题目描述 Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone co ...

  2. 【POJ3662】Telephone Lines dij + 二分答案

    题目大意:给定一个 N 个顶点,M 条边的无向图,求一条从 1 号节点到 N 号节点之间的路径,使得第 K+1 大的边权最小,若 1 与 N 不连通,输出 -1. 最小化最大值一类的问题,采用二分答案 ...

  3. POJ-3662 Telephone Lines 二分+双端队列

    题目传送门 题意:有n个点, p条路,每条道路有个花费Li, 然后现在要建一条1-n的路线,然后可以选k条道路免费, 然后可以在剩下的道路中选择价格最高的边支付费用, 求这个答案最小. 题解: 二分答 ...

  4. USACO 2008 January Silver Telephone Lines /// 二分最短路 邻接表dijkstra oj22924

    题目大意: 一共有N (1 ≤ N ≤ 1,000)个电线杆,有P P (1 ≤ P ≤ 10,000)对电线杆是可以连接的, 用几条线连接在一起的电线杆之间都可相互通信,现在想要使得电线杆1和电线杆 ...

  5. P1948 [USACO08JAN]Telephone Lines S

    题意描述 在无向图中求一条从 \(1\) 到 \(N\) 的路径,使得路径上第 \(K+1\) 大的边权最小. 等等,最大的最小...如此熟悉的字眼,难道是 二分答案. 下面进入正题. 算法分析 没错 ...

  6. POJ 3662 Telephone Lines (二分+Dijkstra: 最小化第k大的值)

    题意 Farmer John想从电话公司修一些电缆连接到他农场.已知N个电线杆编号为1,2,⋯N,其中1号已经连接电话公司,N号为农场,有P对电线杆可连接. 现给出P对电线杆距离Ai,Bi,Li表示A ...

  7. 洛谷 P1824 进击的奶牛 【二分答案】(求最大的最小值)

    题目链接:https://www.luogu.org/problemnew/show/P1824 题目描述 Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚, ...

  8. 【BZOJ1579】Revamping Trails(分层图,最短路,堆)

    题意:每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= ...

  9. [USACO08JAN]Telephone Lines

    嘟嘟嘟 题意概括一下,就是在无向图上求一条1到n的路径,使路径上第k + 1大的边权尽量小. 考虑dp,令dp[i][j] 表示走到节点 i,路线上有 j 条电话线免费时,路径上最贵的电缆花费最小是多 ...

随机推荐

  1. Win10环境下使用Flask配合Celery异步推送实时/定时消息(Socket.io)/2020年最新攻略

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_163 首先得明确一点,和Django一样,在2020年Flask 1.1.1以后的版本都不需要所谓的三方库支持,即Flask-Ce ...

  2. [b01lers2020]Welcome to Earth-1

    1.打开之后界面如下,查看源代码信息,发现chase文件,结果如下: 2.访问chase文件会一直跳转到die界面,那就只能抓包进行查看,发现leftt文件,结果如下: 3.访问leftt文件并查看源 ...

  3. 从零开始Blazor Server(6)--基于策略的权限验证

    写这个的原因 现在BootstrapBlazor处于大更新时期,Menu组件要改为泛型模式. 本来我们的这一篇应该是把Layout改了,但是改Layout肯定要涉及到菜单,如果现在写了呢,就进入一个发 ...

  4. Python 汽车之家 全系车型参数(包含历史停售车型) 最全

    本文仅供学习交流使用,如侵立删!联系方式及demo下载见文末 汽车之家2021 全系车型参数(包含历史停售车型) 2021.10.21更新 增加参数:电动扰流板.无框设计车门.隐藏电动门把手.自动驾驶 ...

  5. gitpod.io,云端开发调试工具。

    gitpod,一款在线开发调试工具,使用它你可以在网页上直接开发软件项目了. 比如你的项目仓库在github上,你可以直接在网址的前面添加gitpod.io/#,然后回车就能在网页上使用vscode打 ...

  6. POJ2201 Cartesian Tree (cartesian tree)

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  7. [HDU6057] Kanade‘s convolution (FWT)

    题面 出自HDU6057 给你两个数列 A [ 0... 2 m − 1 ] A[0...2^m-1] A[0...2m−1] 和 B [ 0... 2 m − 1 ] B[0...2^m-1] B[ ...

  8. Little Girl and Problem on Trees

    题意 给定一棵无边权的树,最多只有一个点度数超过2,有两种操作 1)(0 u x d)将距离u节点d距离之内的节点的值加上x 2)(1 u)询问u节点的值 n<=100000,q<=100 ...

  9. 【MySQL】从入门到掌握1-一些背景知识

    这个系列的文章带各位学习MySQL数据库. 不需要任何基础知识,便可以学习. 学习MySQL对学习Java的JDBC有很大的好处! 想要开发游戏服务器,那么学习MySQL也是必不可少的. 学习完本系列 ...

  10. KingbaseES 普通表在线改为分区表案例

    对大表进行分区,但避免长时间锁表 假设您有一个应用程序,该应用程序具有一个巨大的表,并且需要始终可用.它变得如此之大,以至于在不对其进行分区的情况下对其进行管理变得越来越困难.但是,您又不能使表脱机以 ...