题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688

题目大意:给n个点,m条有向边。再给出起点s, 终点t。求出s到t的最短路条数+次短路条数。

思路:

1.最短路和次短路是紧密相连的,在最短路松弛操作中,当我们找到一条更短的路径,也就意味着之前的路径不再是最短路,而成为了次短路,利用这个关系可以实现状态的转移。

2.好久没写优先队列了,都忘记了加个 priority_queue, 这样才能写重载,才能排序。

注释在代码里:

 #include<stdio.h>
#include<string.h>
#include<queue>
#define mem(a, b) memset(a, b, sizeof(a))
const int inf = 0x3f3f3f3f;
using namespace std; int n, m;
int tot, head[];
int dis[][], cnt[][];//dis数组记录最短路 0 和次短路 1 距离,cnt数组记录最短路 0 和次短路 1 条数
int vis[][]; struct Edge
{
int to, next;
int w;
}edge[]; void add(int a, int b, int w)
{
edge[++ tot].to = b;
edge[tot].w = w;
edge[tot].next = head[a];
head[a] = tot;
} struct Node//优先队列优化结构体,id为点的序号, dis为源点到该点的距离 p区分属于最短路还是次短路
{
int id, dis, p;
bool operator < (const Node &a)const
{
return dis > a.dis;
}
}no; void init()
{
mem(head, -), tot = ;
mem(vis, ); //代表源点到该点的距离未被确定
} void dij(int s, int t)
{
priority_queue<Node> Q;
while(!Q.empty())
Q.pop();
for(int i = ; i <= n; i ++) //初始化
{
dis[][i] = dis[][i] = inf;
cnt[][i] = cnt[][i] = ;
}
dis[][s] = ;
cnt[][s] = ;//源点到自己的最短路条数为1
no.p = , no.dis = , no.id = s;
Q.push(no);
while(!Q.empty())
{
Node a = Q.top();
Q.pop();
if(vis[a.p][a.id])
continue; //该p状态下已经确定过就跳过
vis[a.p][a.id] = ;
for(int i = head[a.id]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(dis[][to] > dis[a.p][a.id] + edge[i].w) //最短路可以更新(在0或1状态下找到一条更短的路)
{
dis[][to] = dis[][to]; //原来的最短路成为次短路
dis[][to] = dis[a.p][a.id] + edge[i].w;
cnt[][to] = cnt[][to];//次短路条数继承为原来的最短路条数
cnt[][to] = cnt[a.p][a.id];
no.p = , no.dis = dis[][to], no.id = to;
Q.push(no);
no.p = , no.dis = dis[][to], no.id = to;
Q.push(no);
}
else if(dis[][to] == dis[a.p][a.id] + edge[i].w)//最短路长度一样 更新最短路条数即可
{
cnt[][to] += cnt[a.p][a.id];
}
else if(dis[][to] > dis[a.p][a.id] + edge[i].w)//找到一条长度大于最短路但小于当前次短路的路径
{//将这条路变成次短路
dis[][to] = dis[a.p][a.id] + edge[i].w;
cnt[][to] = cnt[a.p][a.id];
no.p = , no.dis = dis[][to], no.id = to;
Q.push(no);
}
else if(dis[][to] == dis[a.p][a.id] + edge[i].w)
{
cnt[][to] += cnt[a.p][a.id];
}
}
}
} int main()
{
int T;
scanf("%d", &T);
while(T --)
{
init();
scanf("%d%d", &n, &m);
for(int i = ; i <= m; i ++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
int s, t;
scanf("%d%d", &s, &t);
dij(s, t);
int ans = cnt[][t]; //ans代表最短路的条数
if(dis[][t] + == dis[][t])
ans += cnt[][t];
printf("%d\n", ans);
}
return ;
}

最新文章

  1. Windows内核遍历驱动模块源码分析
  2. 同一台机子上用多个git 账号
  3. VC++ 两种动态调整控件位置的方法(CButton设置为Radio形式会出现错误)
  4. jsonp原理
  5. 功能完善的Java连接池调用实例
  6. 做完c语言作业的心得
  7. gnuplot Python API
  8. Kik CEO Ted Livingston发博称要成为西方的微信?
  9. php学习日志(1)-php介绍
  10. php插件机制实现原理
  11. php 利用第三方软件进行网页快照
  12. MySQL user表root用户误删除后恢复
  13. CLR Profiler 性能分析工具
  14. Windows 和 Mac 系统下安装git 并上传,修改项目
  15. 解决Ubuntu 16.04 上Android Studio2.3上面运行APP时提示DELETE_FAILED_INTERNAL_ERROR Error while Installing APKs的问题
  16. 洛谷 P2622 关灯问题II(状压DP入门题)
  17. php 判断客户端是否为手机端访问
  18. php包含那点事情[WOOYUN]
  19. C标准库string.h中几个常用函数的使用详解
  20. 【poj3420】 Quad Tiling

热门文章

  1. docker管理
  2. Oracle查看锁表和解锁
  3. PHP mysqli_field_tell() 函数
  4. vue-cli3项目首页加载速度优化(cdn加速,路由懒加载,gzip压缩)
  5. Selenium定位class包含空格的元素-复合class节点
  6. deepin linux安装为知笔记
  7. 泛目录程序(莲花泛目录程序/黑帽SEO/寄生虫/莲花泛目录解析/泛目录软件)
  8. C++11正则表达式初探
  9. HSBToolBox
  10. Error, DNGuard Runtime library not loaded!