问题描述

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 路由选择问题 (最短路+次短路)的更多相关文章

  1. 算法笔记--次小生成树 && 次短路 && k 短路

    1.次小生成树 非严格次小生成树:边权和小于等于最小生成树的边权和 严格次小生成树:    边权和小于最小生成树的边权和 算法:先建好最小生成树,然后对于每条不在最小生成树上的边(u,v,w)如果我们 ...

  2. CSU 2005 Nearest Maintenance Point(最短路+bitset)

    https://vjudge.net/problem/CSU-2005 题意:给出带权值的图,图上有一些特殊点,现在给出q个询问,对于每个询问,输出离该点最近的特殊点,如果有多个,则按升序输出. 思路 ...

  3. php短路与 短路或

    关于php短路的问题特性,三种写法的区别 $a = 1;$b=0;第一种: $a && $b = 'cccccccc';第二种 $a || $b = 'cccccccc';第三种 if ...

  4. hdu 2544最短路——最短路的初次总结 UESTC 6th Programming Contest Online

    这是一道标准的模板题,所以拿来作为这一段时间学习最短路的总结题目. 题意很简单: 有多组输入数据,每组的第一行为两个整数n, m.表示共有n个节点,m条边. 接下来有m行,每行三个整数a, b, c. ...

  5. BZOJ 1726: [Usaco2006 Nov]Roadblocks第二短路( 最短路 )

    从起点和终点各跑一次最短路 , 然后枚举每一条边 , 更新answer ---------------------------------------------------------------- ...

  6. HDU2544-最短路(最短路模版题目)

    Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要 ...

  7. 最短路 次短路 k短路(k很小)

    最短路 luogu 3371 https://www.luogu.org/problemnew/show/P3371 #include <cstdio> #include <cstd ...

  8. LOJ#6354. 「CodePlus 2018 4 月赛」最短路[最短路优化建图]

    题意 一个 \(n\) 个点的完全图,两点之间的边权为 \((i\ xor\ j)*C\) ,同时有 \(m\) 条额外单向路径,问从 \(S\) 到 \(T\) 的最短路. \(n\leq 10^5 ...

  9. BZOJ1726: [Usaco2006 Nov]Roadblocks第二短路 K短路

    Description 贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友.贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样, ...

随机推荐

  1. 总结MySQL修改最大连接数的两个方式

    最大连接数是可以通过mysql进行修改的,mysql数据库修改最大连接数常用有两种方法,今天我们分析一下这两种方法之间的特点和区别,以便我们能更好的去维护mysql.下面我们来看一下mysql修改最大 ...

  2. [转帖]三大运营商2G/3G/4G频率分配和网络制式

    三大运营商2G/3G/4G频率分配和网络制式 https://blog.csdn.net/weixin_38759340/article/details/80890142 经过二十多年长期的发展,我国 ...

  3. GraphQL & REST API

    GraphQL & REST API GraphQL https://mp.weixin.qq.com/s/X-jm7jLXWmMmLBVgHfkRiQ https://webapplog.c ...

  4. jmeter 正则表达式提取

    引用名称:自己定义的变量名称,后续请求将要引用到的变量名,如填写的是:id,后面的引用方式是${id} 正则表达式:提取内容的正则表达式,相当于lr中的关联函数 [()     括起来的部分就是需要提 ...

  5. matlab中 assert(any(mask(:)));

    首先,matlab中any函数:检测矩阵mask中是否有非零元素,如果有,返回1,:如果没有非零元素,即所有元素都是0,那么则返回0. assert()是一个调试程序时经常使用的宏,在程序运行时它计算 ...

  6. python自动化之web抓取

    ''' 从web抓取数据: webbrowser:是python自带的,打开浏览器获取指定页面. requests:从因特网上下载文件和网页. Beautiful Soup:解析HTML,即网页编写的 ...

  7. BibTex相关

    标签(空格分隔): 杂七杂八的问题 又到了写论文的高峰期(?)在BibTeX中添加参考文献时,发现选项很多,对一些称呼还是一脸懵逼..阿一古,也许是最后一次写论文了,还弄清楚的还是清楚一下吧~ [转自 ...

  8. selenium实战之斗鱼弹幕

    python3.6.selenium.chromedriver 先上代码 from selenium import webdriver from time import sleep driver=we ...

  9. STL 算法介绍

    STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成.        <algorithm ...

  10. 洛谷P4233 射命丸文的笔记 【多项式求逆】

    题目链接 洛谷P4233 题解 我们只需求出总的哈密顿回路个数和总的强联通竞赛图个数 对于每条哈密顿回路,我们统计其贡献 一条哈密顿回路就是一个圆排列,有\(\frac{n!}{n}\)种,剩余边随便 ...