题目如下(By cwx)

【题目描述】 给你一张含有 n 个点 m 条边的联通无向图,记录 1 号点到每个点的最短路长度,询问
去掉与 i 号相邻的所有边后,1 号点到多少个点的最短路长度改变,若不连通则也视为改
变。
【输入数据】 第一行两个正整数 n,m, 接下来 m 行,每行三个正整数数 i,j,k,表示一条边<i,j>,长度为 k。
【输出数据】 N 行,第 i 行表示去掉与 i 号相邻的所有边后,1 号点到多少个点的最短路长度改变。
【输入样例】
2 1
1 2 1
【输出样例】
1
1
【数据约定】
30% n <= 100,m <= 300
100% n <= 5000,m <= 20000,边权均为不超过 100 的正整数。 

1.裸做法

每次孤立一些边,重新做spfa

2.转化为求必经点

到点n的最短路的必经点由多条(可能只有1条)可至n的最短路的点取交集得到。

可以依次递推得到,但是取交集的过程需要消耗一些时间与空间复杂度。

3.改进

将到各个点的最短路孤立出来新建一个图(到任意点的所有最短路都要孤立出来),且孤立出来的都是有向图,不妨设新图点数为N2

为什么可以这样呢?因为若一个点不在到任一其他点的最短路上,那么即使删去了它也不会影响到达其余任何点的长度。

<1.如果不孤立出来:

无论是写dfs还是bfs,松弛次数就会相当大,相比之下不如重新做一遍spfa,则又绕回了裸做法。

<2.如果孤立出来:

i.假设写dfs,就只需要求得在新图上除去某点后,最多能到达的点数,不妨设最多为N3个点,则答案为N2 – N­­3。在线输出即可。

ii.假设写bfs,从要删的点开始,每扫到一个点就将其入度 -1 ,将入度为0的点进队。入度为0代表仅有唯一的一条已经被堵的最短路经过此点,于是将此点进队。所以最后队列的长度即为1号点到其他点最短路长度改变的个数。

其实主要算法就已经结束了,但是如何孤立出一个图却并没有讨论。事实上,利用第一次spfa的成果(dist数组),当dist[u] + worth[i] == dist[point[i]]时,则此边必定是到某点的最短路上的边。

dfs的时间在0.5s一个点左右,bfs在0.02s一个点左右,若是理解上述算法,那么造成差异的原因应该是显然的啵

不过编程复杂度差不多,有兴趣的可以都写写

贴下我没缩行过的code吧

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <memory>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;const int maxn = 5000 + 5;
const int maxm = 20000 * 2 + 5;
const int status = 30000 + 5;typedef int INT[maxm];
typedef int INTT[maxn];int n, m, e(1), E(1), tnum(1);
INT ne, po; INTT ed;
INT next, point, worth;
INTT edge, dist, vp, tmp;
int s[status], L, R;void init(), spfa(), solve();
void newgraph(int), dfs(int, int);
void addedge(int, int, int), link(int , int);int main()
{freopen("spfa.in", "r", stdin);freopen("spfa.out", "w", stdout);init();spfa();solve();fclose(stdin); fclose(stdout);return 0;
}void init()
{cin >> n >> m;for (int i = 1, u, v, w; i <= m && scanf("%d%d%d", &u, &v, &w); ++i)addedge(u, v, w), addedge(v, u, w);
}void addedge(int u, int v, int w)
{++e;point[e] = v; next[e] = edge[u]; edge[u] = e; worth[e] = w;
}void link(int u, int v)
{++E;po[E] = v; ne[E] = ed[u]; ed[u] = E;
}void spfa()
{memset(vp, 0, sizeof(vp));memset(dist, 127, sizeof(dist));for (L = R = 1, s[L] = vp[1] = 1, dist[1] = 0; L <= R; vp[s[L++]] = 0)for (int i = edge[s[L]]; i; i = next[i])if (dist[point[i]] > dist[s[L]] + worth[i]){dist[point[i]] = dist[s[L]] + worth[i];if (!vp[point[i]]) vp[point[i]] = 1, s[++R] = point[i];}
}void newgraph(int u)
{for (int i = edge[u]; i; i = next[i])if (dist[point[i]] == dist[u] + worth[i]){link(u, point[i]);if (!vp[point[i]]) { ++tnum; vp[point[i]] = 1; }newgraph(point[i]);}
}void dfs(int u, int limt)
{for (int i = ed[u]; i; i = ne[i]){if (po[i] == limt) continue;if (!tmp[po[i]]) tmp[po[i]] = 1, ++tmp[0],dfs(po[i], limt);}
}void solve()
{//1int tot = 0;for (int i = 2; i <= n; ++i)if (dist[i] != dist[0]) ++tot;cout << tot << endl;//makegraphmemset(vp, 0, sizeof(vp));for (int i = 1; i <= n; ++i)if (!vp[i]) newgraph(i);//2for (int i = 2; i <= n; memset(tmp, 0, sizeof(tmp)), ++i)dfs(1, i), cout << tnum - 1 - tmp[0] << endl;
}

【SPFA + DFS/BFS】最短路的一个拓展题相关推荐

  1. 洛谷 P1710 地铁涨价 (dfs+bfs)

    地铁涨价 题目描述 博艾市除了有海底高铁连接中国大陆.台湾与日本,市区里也有很成熟的轨道交通系统.我们可以认为博艾地铁系统是一个无向连通图.博艾有N个地铁站,同时有M小段地铁连接两个不同的站. 地铁计 ...

  2. 【PAT】【spfa + dfs】1030 Travel Plan (30 分)

    题目链接:1030 Travel Plan (30 分) A traveler's map gives the distances between cities along the highways, ...

  3. 数据结构——dfs/bfs

    文章目录 dfs/bfs 迷宫 OpenJ_Bailian - 2790 走迷宫 OpenJ_Bailian - 3752 迷宫问题 POJ - 3984 迷宫(一) 计蒜客 - T1595 迷宫(二 ...

  4. spfa 单源最短路究极算法

    学习博客链接:SPFA 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm.      SPFA算法是西南交通大学段凡丁于1994年发表的.     从名 ...

  5. 【DFS/BFS】NYOJ-58-最少步数(迷宫最短路径问题)

    [题目链接:NYOJ-58] 经典的搜索问题,想必这题用广搜的会比较多,所以我首先使的也是广搜,但其实深搜同样也是可以的. 不考虑剪枝的话,两种方法实践消耗相同,但是深搜相比广搜内存低一点. 我想,因 ...

  6. POJ2308连连看dfs+bfs+优化

    DFS+BFS+MAP+剪枝 题意:       就是给你一个10*10的连连看状态,然后问你最后能不能全部消没? 思路:      首先要明确这是一个搜索题目,还有就是关键的一点就是连连看这个游戏是 ...

  7. 链式前向星模板 建图+dfs+bfs+dijkstra

    边没有用struct封装起来,节点和边的计数起点如果不符合习惯可以稍作修改 建图+DFS+BFS #include <cstdio> #include <cstring> #i ...

  8. POJ 2251 Dungeon Master (BFS最短路)

    三维空间里BFS最短路 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #incl ...

  9. 算法 - DFS/BFS

    DFS函数大概率会传递"位置信息",根据位置信息获取下一步的选择,(大部分是在循环中)选择.执行.回退 例如N皇后的 棋盘位置(x, y),组合问题的 idx DFS函数的目的是, ...

最新文章

  1. java 获取linux mac_java在linux获得ip地址和mac
  2. Postgresql: 时间戳long,TimeStamp,Date,String互转
  3. 如何使用消息队列解决分布式事物?
  4. Ecol. Lett. | 生态学实验设计中“梯度实验”和“重复实验”的抉择
  5. linux系统编程_Linux系统编程:进程间通信
  6. linux端口监听命令
  7. 动态规划 HDU1231-------最大连续子序列
  8. HDU2650(高斯整数环)
  9. c++程序设计中虚基类,多继承知识点
  10. 网站前端,后端设计,系统设计常识
  11. 2021高通人工智能应用创新大赛--创新赛道-决赛阶段小结
  12. 文字的多列布局--column
  13. python解读器_Python装饰器完全解读
  14. 计算机毕业设计ssm+sqlserver房屋租赁管理系统
  15. Win10安装Centos7双系统
  16. *(uint32_t *)(PERIPH) == GPIOX)
  17. 牛客小白月赛2 H 武 【Dijkstra】
  18. Openbravo ERP 3.0安装指南
  19. zip压缩到指定目录
  20. WPF ShowDialog切换其他应用后不显示的问题

热门文章

  1. 从三室心脏MRI影像检测主动脉瓣病变
  2. 零信任态势评估:CIS安全控制内容与实施
  3. 支持GIF动画的ImageView
  4. java程序员自我简介及简历
  5. win7 APPCRASH(解决方法)(转)
  6. 一一数落2006几大“恶心”事件
  7. 一文搞懂什么是图神经网络GNN【入门教程】
  8. 区块链之一 起源思想和本质
  9. 新手小白,做这几个短视频自媒体平台,有播放量就有收益
  10. Sigar获取系统信息