HAOI 2005 路由选择问题 (最短路+次短路)
问题描述
X城有一个含有N个节点的通信网络,在通信中,我们往往关心信息从一个节点I传输到节点J的最短路径。遗憾的是,由于种种原因,线路中总有一些节点会出故障,因此在传输中要避开故障节点。
任务一:在己知故障节点的情况下,求避开这些故障节点,从节点I到节点J的最短路径S0。
任务二:在不考虑故障节点的情况下,求从节点I到节点J的最短路径S1、第二最短路径S2。
输入文件
第1行: N I J (节点个数 起始节点 目标节点)
第2—N+1行: Sk1 Sk2…SkN (节点K到节点J的距离为SkJ K=1,2,……,N)
最后一行: P T1 T2……Tp (故障节点的个数及编号)
输出文件
S0 S1 S2 (S1<=S2 从节点I到节点J至少有两条不同路径)
样例输入
5 1 5
0 10 5 0 0
10 0 0 6 20
5 0 0 30 35
0 6 30 0 6
0 20 35 6 0
1 2
样例输出
40 22 30
约束条件
(1)N<=50 N个节点的编号为1,2,…,N
(2)Skj为整数,Skj<=100,(K,J=1,2…,N 若Skj=0表示节点K到节点J没线路)
(3)P<=5
思路:
首先简单的说一下次短路经:
次短路径可以看作是k短路径问题的一种特殊情况,求k短路径有Yen算法等较为复杂的方法,对于次短路径,可以有更为简易的方法。下面介绍一种求两个顶点之间次短路径的解法。
我们要对一个有向赋权图(无向图每条边可以看作两条相反的有向边)的顶点S到T之间求次短路径,首先应求出S的单源最短路径。遍历有向图,标记出可以在最短路径上的边,加入集合K。然后枚举删除集合K中每条边,求从S到T的最短路径,记录每次求出的路径长度值,其最小值就是次短路径的长度。
在这里我们以为次短路径长度可以等于最短路径长度,如果想等,也可以看作是从S到T有不止一条最短路径。如果我们规定求从S到T大于最短路径长度的次短路径,则答案就是每次删边后大于原最短路径的S到T的最短路径长度的最小值。
用Dijkstra+堆求单源最短路径,则每次求最短路径时间复杂度为O(Nlog(N+M) + M),所以总的时间复杂度为O(NM*log(N+M) + M^2)。该估计是较为悲观的,因为一般来说,在最短路径上的边的条数要远远小于M,所以实际效果要比预想的好。
对于前面两个询问,直接spfa即可(同时记录最短路径),对于第三个询问,每一次删掉最短路径中的一条边,然后再spfa找到删过边后的最短路,即为次短路。
代码:
#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
const int INF=0x3f3f3f3f;
using namespace std;
int n,st,ed,cnt,st1,ed1;
struct Node
{
int to,val;
int Next;
}node[2600];
int head[55];//头结点
int pro[55];//有问题的点
int pre[55];//前去节点
int dis[55];//距离
int vis[55];//标记有没有访问过
void init()
{
for(int i=0;i<=n;i++)
head[i]=-1;
}
void add(int a,int b,int w)
{
node[cnt].to=b;
node[cnt].val=w;
node[cnt].Next=head[a];
head[a]=cnt;
cnt++;
}
void spfa(int flag)
{
if(flag==1)
memset(pre,0,sizeof(pre));
queue<int>q;
for(int i=1;i<=n;i++)
{
dis[i]=INF;
vis[i]=0;
}
dis[st]=0;
vis[st]=1;
pre[st]=-1;
q.push(st);
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i!=-1;i=node[i].Next)
{
int y=node[i].to;
if ((x == st1 && y == ed1) || (x == ed1 && y == st1)) continue;
if(pro[y]==1) continue;//第一次找最短路的时候遇见故障点要跳过
if(dis[y]>dis[x]+node[i].val)
{
dis[y]=dis[x]+node[i].val;
if(flag==1) pre[y]=x;
if(vis[y]==0)
{
vis[y]=1;
q.push(y);
}
}
}
}
}
int main()
{
while(scanf("%d%d%d",&n,&st,&ed))
{
init();
cnt=0;
int w,num;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
scanf("%d",&w);
if(w!=0)
{
add(i,j,w);//按照头插法保存下图的信息
}
}
scanf("%d",&w);
for(int i=1;i<=w;i++)//将有问题的点标记下来
{
scanf("%d",&num);
pro[num]=1;
}
//去掉有故障的点寻找最短路
spfa(1);
printf("%d ",dis[ed]);
//不考虑有故障的点寻找最短路
memset(pro,0,sizeof(pro));
spfa(1);
printf("%d ",dis[ed]);
//求次短路是在不考虑有故障的点的基础的
int Min=INF;
int v ;
v=ed;//倒着一条边一条边的删除
while(pre[v]!= -1)
{
st1=pre[v];//删除的这条边的起始点
ed1=v;//删除的这条边的终点
spfa(0);
Min=min(Min,dis[ed]);//然后在这些最短路里面找一条最小的
v=pre[v];
}
printf("%d\n",Min);
}
return 0;
}
HAOI 2005 路由选择问题 (最短路+次短路)的更多相关文章
- 算法笔记--次小生成树 && 次短路 && k 短路
1.次小生成树 非严格次小生成树:边权和小于等于最小生成树的边权和 严格次小生成树: 边权和小于最小生成树的边权和 算法:先建好最小生成树,然后对于每条不在最小生成树上的边(u,v,w)如果我们 ...
- CSU 2005 Nearest Maintenance Point(最短路+bitset)
https://vjudge.net/problem/CSU-2005 题意:给出带权值的图,图上有一些特殊点,现在给出q个询问,对于每个询问,输出离该点最近的特殊点,如果有多个,则按升序输出. 思路 ...
- php短路与 短路或
关于php短路的问题特性,三种写法的区别 $a = 1;$b=0;第一种: $a && $b = 'cccccccc';第二种 $a || $b = 'cccccccc';第三种 if ...
- hdu 2544最短路——最短路的初次总结 UESTC 6th Programming Contest Online
这是一道标准的模板题,所以拿来作为这一段时间学习最短路的总结题目. 题意很简单: 有多组输入数据,每组的第一行为两个整数n, m.表示共有n个节点,m条边. 接下来有m行,每行三个整数a, b, c. ...
- BZOJ 1726: [Usaco2006 Nov]Roadblocks第二短路( 最短路 )
从起点和终点各跑一次最短路 , 然后枚举每一条边 , 更新answer ---------------------------------------------------------------- ...
- HDU2544-最短路(最短路模版题目)
Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要 ...
- 最短路 次短路 k短路(k很小)
最短路 luogu 3371 https://www.luogu.org/problemnew/show/P3371 #include <cstdio> #include <cstd ...
- LOJ#6354. 「CodePlus 2018 4 月赛」最短路[最短路优化建图]
题意 一个 \(n\) 个点的完全图,两点之间的边权为 \((i\ xor\ j)*C\) ,同时有 \(m\) 条额外单向路径,问从 \(S\) 到 \(T\) 的最短路. \(n\leq 10^5 ...
- BZOJ1726: [Usaco2006 Nov]Roadblocks第二短路 K短路
Description 贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友.贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样, ...
随机推荐
- [转帖]HTTPS系列干货(一):HTTPS 原理详解
HTTPS系列干货(一):HTTPS 原理详解 https://tech.upyun.com/article/192/HTTPS%E7%B3%BB%E5%88%97%E5%B9%B2%E8%B4%A7 ...
- Vue 小组件input keyup.enter绑定
<div id="todo-list-example"> <input v-model="newTodoText" v-on:keyup.en ...
- AtCoder Regular Contest 081
C - Make a Rectangle 从大到小贪心即可. # include <bits/stdc++.h> using namespace std; map<int,int&g ...
- 对final和static的理解
一.final (一).final的使用 final关键字可以用来修饰类.方法和变量(包括成员变量和局部变量) 1. 当用final修饰一个类时,表明这个类不能被继承.2. 当用final修饰一个方法 ...
- Educational Codeforces Round 56 Div. 2 翻车记
A:签到. B:仅当只有一种字符时无法构成非回文串. #include<iostream> #include<cstdio> #include<cmath> #in ...
- 使用简单zzupdate命令轻松升级Ubuntu到较新版本
zzupdate是一个开源的命令行实用程序,通过将几个更新命令组合到一个命令中,使得将Ubuntu桌面版和服务器版升级到更新版本的任务变得容易一些. 将Ubuntu系统升级到更新的版本并不是一项艰巨的 ...
- ORA-01410: 无效的 ROWID
视图查询单表是有这个东西的,但是视图的SQL涉及多表关联,就没这个rowid了,要么自己写个,要么不用这个ROWID做啥动作
- vs2013 查找进行的过程中被停止
VS"Find in Files"失效的解决方法一:让VS窗口获得焦点,依次按以下快捷键Ctrl+BreakCtrl+Scroll LockAlt+Break VS"Fi ...
- 学习Spring Boot:(六) 集成Swagger2
前言 Swagger是用来描述和文档化RESTful API的一个项目.Swagger Spec是一套规范,定义了该如何去描述一个RESTful API.类似的项目还有RAML.API Bluepri ...
- 【BZOJ4140】共点圆加强版(二进制分组)
[BZOJ4140]共点圆加强版(二进制分组) 题面 BZOJ 题解 我卡精度卡了一天.... 之前不强制在线的做法是\(CDQ\)分治,维护一个凸壳就好了. 现在改成二进制分组,每次重建凸壳就好了. ...