P2865 【[USACO06NOV]路障Roadblocks】(次短路)
算法
Dijkstra
要求次短路
那么在不考虑重复走一条边的情况下
肯定是把最短路中的一段改成另一段
至少要换另一条边到路径里
所以可以枚举所有不属于最短路的每条边(a,b)
那么dis(1,a)+(a,b)+ dis(b,n)就是一种可能的答案(记为S)
显然如果另一条不属于S的边更新S后会使S更长,就不可能为次短路了
那么只要对起点1和终点n分别跑Dijkstra就可以求出每个dis(1,a)和dis(b,n)
至于判断一条边是否在最短路上也很容易:
显然,如果dis(1,a)+(a,b)=dis(1,b),那么边(a,b)就在最短路径上
然后考虑重复走一条边情况(显然也只要考虑重复走一条边的情况)
也很简单,用贪心的思想
找到最短路径上最短的边(a,b),如果重复走一条边的情况为次短路,那么肯定是dis(1,n)+(a,b)*2 (走过去又走回来,要乘2)
如果(c,d)不是最短的边,那么dis(1,n)+(c,d)*2肯定大于dis(1,n)+(a,b)*2,就不可能是次短路
然后就可以了,实现时要注意一下细节
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
inline int read()
{
int res=;
char ch=getchar();
while(ch>''||ch<'')
ch=getchar();
while(ch>=''&&ch<='')
{
res=res*+ch-'';
ch=getchar();
}
return res;
}
struct node//存Dijkstra的优先队列中的数据
{
int u,v;//v为点的编号,u表示从起点到v的距离
bool operator < (const node &b) const{
return u>b.u;
}
};
priority_queue <node> q;//为Dijkstra开的优先队列
struct edge
{
int from,to,z;
}e[];
int fir[],cnt;//链式前向星存图
inline void add(int a,int b,int c)
{
e[++cnt].from=fir[a];
fir[a]=cnt;
e[cnt].to=b;
e[cnt].z=c;
}//加边
int n,m,ans=;
int dis[][];
//dis[][0]为起点到各个点的距离,dis[][1]为终点到各个点的距离
inline void dijk(int sta,int k)
//sta为开始点,k为dis的第二维
{
dis[sta][k]=;
node p;
p.u=; p.v=sta;
q.push(p);
while(q.empty()==)
{
int u=q.top().u,v=q.top().v;
q.pop();
if(u!=dis[v][k]) continue; //优化
for(int i=fir[v];i;i=e[i].from)
{
int to=e[i].to;
if(dis[to][k]>dis[v][k]+e[i].z)
{
dis[to][k]=dis[v][k]+e[i].z;
p.u=dis[to][k]; p.v=to;
q.push(p);
}
}
}
}//Dijkstra的模板
struct data
{
int x,y,z;
}d[];//存读入的数据
int main()
{
memset(dis,0x7f,sizeof(dis));
int a,b,c,mi=;//mi表示最短路径上最短的边长
cin>>n>>m;
for(int i=;i<=m;i++)
{
a=read(); b=read(); c=read();
d[i].x=a; d[i].y=b; d[i].z=c;
add(a,b,c); add(b,a,c);
}//读入
dijk(,); dijk(n,);//跑最短路
int mx=dis[n][];
for(int i=;i<=m;i++)
//考虑不重复走一条边的情况
{
int x=d[i].x,y=d[i].y;
if(dis[x][]+dis[y][]>dis[y][]+dis[x][]) swap(x,y);
//重要的细节,1到x的路径不能和y到n的路径重复
int s=dis[x][]+dis[y][];
if(s+d[i].z==mx) continue;//判断边(x,y)是否在最短路径上,如果在就不能选
ans=min(ans,s+d[i].z);//否则就尝试更新答案
}
for(int i=;i<=m;i++)
//考虑重复走一条边的情况,显然只要考虑在最短路径上的边
{
int x=d[i].x,y=d[i].y;
if(dis[x][]+dis[y][]>dis[y][]+dis[x][]) swap(x,y);
//同样,1到x的路径不能和y到n的路径重复
if(dis[x][]+dis[y][]+d[i].z!=mx) continue;//如果边(x,y)不在最短路径上就不能考虑
mi=min(mi,d[i].z);//尝试更新mi
}
ans=min(ans,mx+mi*);//答案取较小值
cout<<ans;
return ;
}
P2865 【[USACO06NOV]路障Roadblocks】(次短路)的更多相关文章
- 洛谷P2865 [USACO06NOV]路障Roadblocks——次短路
给一手链接 https://www.luogu.com.cn/problem/P2865 这道题其实就是在维护最短路的时候维护一下次短路就okay了 #include<cstdio> #i ...
- P2865 [USACO06NOV]路障Roadblocks
P2865 [USACO06NOV]路障Roadblocks 最短路(次短路) 直接在dijkstra中维护2个数组:d1(最短路),d2(次短路),然后跑一遍就行了. attention:数据有不同 ...
- 洛谷——P2865 [USACO06NOV]路障Roadblocks
P2865 [USACO06NOV]路障Roadblocks 题目描述 Bessie has moved to a small farm and sometimes enjoys returning ...
- 络谷 P2865 [USACO06NOV]路障Roadblocks
P2865 [USACO06NOV]路障Roadblocks 题目描述 Bessie has moved to a small farm and sometimes enjoys returning ...
- luogu2865 [USACO06NOV]路障Roadblocks 次短路
注意:如果是这么个写法,堆数组要开成n+m的. 为什么呢?设想一下从1到2有m条长度递减的路,这岂不是要入队m次-- #include <algorithm> #include <i ...
- POJ——T 3255 Roadblocks|| COGS——T 315. [POJ3255] 地砖RoadBlocks || 洛谷—— P2865 [USACO06NOV]路障Roadblocks
http://poj.org/problem?id=3255 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 15680 ...
- 【洛谷 P2865】 [USACO06NOV]路障Roadblocks(最短路)
题目链接 次短路模板题. 对每个点记录最短路和严格次短路,然后就是维护次值的方法了. 和这题一样. #include <cstdio> #include <queue> #in ...
- 洛谷题解 P2865 【[USACO06NOV]路障Roadblocks】
链接:https://www.luogu.org/problemnew/show/P2865 题目描述 Bessie has moved to a small farm and sometimes e ...
- BZOJ 1726 洛谷 2865 [USACO06NOV]路障Roadblocks【次短路】
·求1到n的严格次短路. [题解] dijktra魔改?允许多次入队,改了次短路的值也要入队. #include<cstdio> #include<algorithm> #de ...
随机推荐
- 让你分分钟了解Web接口测试
因为前后端架构分离技术的兴起,接口测试也越来越重要,最近一直想总结下,作为一个近三年的测试人员,接口这个词是耳濡目染的,而开发张口闭口也都是这个接口或那个接口怎么怎么样,自己遇到的bug也很多是接口问 ...
- [LeetCode] 331. Verify Preorder Serialization of a Binary Tree_Medium tag: stack
One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, ...
- javascript console自动点击页面元素
原文地址https://jingyan.baidu.com/article/0a52e3f41c0b0abf63ed726d.html 这里拿百度音乐VIP兑换页面来做演示. 首先打开百度音乐VIP兑 ...
- C# 拼接字符串的几种方式和性能
开发过程中常用到的拼接字符串的方法有三种: 1 简单 “+=” 拼接法 1 2 3 4 5 string str="a"; str+="c"+"d ...
- [转]C语言四书五经
我们来说说C语言方面的图书.什么,C语言?有读者奇怪了.没错,这一次的主角就是诞生于1973年如今已经儿孙满堂的C语言.我们之所以要谈及C,不仅仅是因为它的影响深远,这完全可以从C系列语言家族的兴旺发 ...
- OS X 下动态库的引用
foo.c #include <stdio.h> void foo(void) { printf("foo.\n"); } main.c #include <st ...
- QQ在线客服,默认到要加好友,授权也不起作用需要先开通QQ营销服务
QQ在线客服,默认到要加好友,授权也不起作用需要先开通QQ营销服务http://wpa.qq.com/msgrd?v=3&uin=你的客服QQ号码&site=qq&menu=y ...
- C/C++之内存分配
一.编译时与运行时的内存情况1.编译时不分配内存编译时是不分配内存的.此时只是根据声明时的类型进行占位,到以后程序执行时分配内存才会正确.所以声明是给编译器看的,聪明的编译器能根据声明帮你识别错误.2 ...
- 5G频谱到底有多值钱?
继9月召开5G峰会并发布“5GFAST”战略后,美国于当地时间11月14日正式启动5G频谱拍卖.“这些频谱对于部署5G服务和应用程序至关重要,而我们并没有就此止步.”美国联邦通信委员会(FCC)主席A ...
- Centos7.5 安装Netdata
切为root, yum install zlib-devel gcc make git autoconf autogen guile-devel automake pkgconfig -y yum i ...