题目描述

“您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。
比荷卢经济联盟有很多公交线路。
每天公共汽车都会从一座城市开往另一座城市。
沿途汽车可能会在一些城市(零或更多)停靠。
旅行社计划旅途从 S 城市出发,到 F 城市结束。
由于不同旅客的景点偏好不同,所以为了迎合更多旅客,旅行社将为客户提供多种不同线路。
游客可以选择的行进路线有所限制,要么满足所选路线总路程为 S 到 F 的最小路程,要么满足所选路线总路程仅比最小路程多一个单位长度。

如上图所示,如果S = 1,F = 5,则这里有两条最短路线1->2->5,1->3->5,长度为6;有一条比最短路程多一个单位长度的路线1->3->4->5,长度为7。
现在给定比荷卢经济联盟的公交路线图以及两个城市 S 和 F,请你求出旅行社最多可以为旅客提供多少种不同的满足限制条件的线路。

输入格式

第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含两个整数 N 和 M,分别表示总城市数量和道路数量。
接下来 M 行,每行包含三个整数 A,B,L,表示有一条线路从城市 A 通往城市 B,长度为 L。
需注意,线路是 单向的,存在从A到B的线路不代表一定存在从B到A的线路,另外从城市A到城市B可能存在多个不同的线路。
接下来一行,包含两个整数 S 和 F,数据保证 S 和 F 不同,并且S、F之间至少存在一条线路。

输出格式

每组数据输出一个结果,每个结果占一行。
数据保证结果不超过109。

数据范围

2≤N≤1000,
1≤M≤10000,
1≤L≤1000,
1≤A,B,S,F≤N

输入样例
2
5 8
1 2 3
1 3 2
1 4 5
2 3 1
2 5 3
3 4 2
3 5 4
4 5 3
1 5
5 6
2 3 1
3 2 1
3 1 10
4 5 2
5 2 7
5 2 7
4 1
输出样例
3
2

题目分析

如果之前没做过最短路求方案数这类题目的话,建议先看看这个题:最短路计数(本题的低配版,该题中与本题相同的知识点就不重复说了)。
这道题目其实就是让我们求最短路和次短路的方案数。
因此这道题的配置几乎和最短路计数是一样的:
dist[][2] //记录最短路和次短路、cnt[][2] //记录最短路和次短路的方案数、st[][2] //判重数组
这道题也是只能用bfs和dijkstra算法来求解,(不知道为什么不能用spfa可以看上面的那道题)但是这道题的边都是有权边了,不能用bfs。因此这道题我们要用dijkstra算法

用dijkstra算法之前我们需要确定一件事情:因为这道题要求两种路径(最短路和次短路),因此dijkstra算法中的优先队列不能只保存点的编号id和最短距离dist,我们还需要记录类型type来表示当前这个路径是最短路还是次短路(统一用0表示最短路,1表示次短路)。

把前面的准备条件都想清楚之后,这道题其实也就没什么难度了。剩下的就是dijkstra算法求解答案了:
(dijkstra算法的基本框架和流程就不都说了,直接讲与普通dijkstra算法不同的地方。)
从优先队列中取出队头元素,假设编号为u,枚举其所有相邻节点v。

  1. 如果dist[u][type]+d[u][v]<dist[v][0],那么更新dist[v][0]=dist[u][type]+d[u][v] 和 dist[v][1]=原v的最短路(原dist[v][0])。
    而cnt[v][0]=cnt[u][type];cnt[v][1]=原v最短路的方案数(原cnt[v][0])
  2. 如果dist[u][type]+d[u][v]==dist[v][0],那么dist[v]的值都不需要更新。
    而cnt[v][0]要加上cnt[u][type];cnt[v][1]不需要变。
  3. 如果dist[u][type]+d[u][v]<dist[v][1],那么需要更新dist[v][1]=dist[u][type]+d[u][v] (dist[v][0]不需要变)。
    而cnt[v][1]=cnt[u][type];(cnt[v][0]不变)
  4. 如果dist[u][type]+d[u][v]==dist[v][1],那么dist[v]的值都不需要更新。
    而cnt[v][1]要加上cnt[u][type];cnt[v][0]不变。

全部求完之后,查看dist[终点][0]与dist[终点][1]+1是否相等。如果相等那么答案为cnt[终点][0]+cnt[终点][1];否则答案为cnt[终点][0]。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=1e3+5,M=2e4+5,INF=0x3f3f3f3f;
struct Node{                //将优先队列中需要的变量封装成结构体int id,type,dist;bool operator>(const Node &a) const{ return dist>a.dist;}
};
int h[N],e[M],w[M],ne[M],idx;
int dist[N][2],cnt[N][2];
bool st[N][2];
void add(int a,int b,int c)
{e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
int dijkstra(int s,int t)       //dijkstra算法求最/次短路及其方案数
{memset(st,0,sizeof st);memset(cnt,0,sizeof cnt);memset(dist,0x3f,sizeof dist);priority_queue<Node,vector<Node>,greater<Node> >heap;dist[s][0]=0; cnt[s][0]=1;heap.push({s,0,0});while(heap.size()){Node t=heap.top();heap.pop();int u=t.id,type=t.type,distance=t.dist,count=cnt[u][type];if(st[u][type]) continue;st[u][type]=true;for(int i=h[u];~i;i=ne[i]){int v=e[i];if(dist[v][0]>distance+w[i]){cnt[v][1]=cnt[v][0];dist[v][1]=dist[v][0];heap.push({v,1,dist[v][1]});cnt[v][0]=count;dist[v][0]=distance+w[i];heap.push({v,0,dist[v][0]});}else if(dist[v][0]==distance+w[i]) cnt[v][0]+=count;else if(dist[v][1]>distance+w[i]){cnt[v][1]=count;dist[v][1]=distance+w[i];heap.push({v,1,dist[v][1]});}else if(dist[v][1]==distance+w[i]) cnt[v][1]+=count;}}int res=cnt[t][0];if(dist[t][0]+1==dist[t][1]) res+=cnt[t][1];return res;
}
int main()
{int t;scanf("%d",&t);while(t--){idx=0;memset(h,-1,sizeof h);int n,m;scanf("%d %d",&n,&m);while(m--)               //建图{int u,v,w;scanf("%d %d %d",&u,&v,&w);add(u,v,w);}int s,t;scanf("%d %d",&s,&t);cout<<dijkstra(s,t)<<endl;}return 0;
}

观光(最短路求方案数2)相关推荐

  1. [01背包] 背包问题求具体方案(01背包+求方案数+思维)

    文章目录 0. 前言 1. 01背包+求方案数+思维 0. 前言 相关: [背包] 背包问题算法模板(模板) 1. 01背包+求方案数+思维 12. 背包问题求具体方案 求方案数也是背包问题.dp 的 ...

  2. 01背包,完全背包,多重背包,混合背包,二维费用背包,分组背包,背包问题求方案数

    1 01背包问题 有 NNN 件物品和一个容量是 VVV 的背包.每件物品只能使用 一次. 第 iii 件物品的体积是 viv_ivi​,价值是 wiw_iwi​.求解将哪些物品装入背包,可使这些物品 ...

  3. 经典背包问题3——背包问题求方案数 、背包问题求具体方案

    经典背包问题3--背包问题求方案数 .背包问题求具体方案 1. 背包问题求方案数 2. 背包问题求具体方案 1. 背包问题求方案数 有 N 件物品和一个容量是 V的背包.每件物品只能使用一次. 第 i ...

  4. [完全背包] 货币系统(完全背包+求方案数)

    文章目录 0. 前言 1. 完全背包+求方案数+思维 0. 前言 相关: [背包] 背包问题算法模板(模板) 强相关: [完全背包] 买书(完全背包+裸题) [完全背包] 货币系统(完全背包+求方案数 ...

  5. 7-30 找单词——多重背包求方案数

    假设有x1个字母A, x2个字母B,- x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,- 字母Z的价值为26.那么,对于给定的字母,可以找到多少价值<=50的单词呢?单词的价值就是 ...

  6. 动态规划之如何将问题抽象转化为0-1背包问题(详解利用动态规划求方案数)

    ⭐️前面的话⭐️ 本篇文章介绍如何对问题抽象转化成0-1背包问题求解和运用0-1背包求方案数.

  7. [01背包] 数字组合(01背包+求方案数)

    文章目录 0. 前言 1. 01背包求方案数 0. 前言 相关: [背包] 背包问题算法模板(模板) 1. 01背包求方案数 278. 数字组合 将 M 看作背包容量,每个数看成一个物品,Ai 看成是 ...

  8. ★ZOJ 3380 Patchouli's Spell Cards 详细题解 (递推+组合数求方案数)

    Patchouli's Spell Cards Time Limit: 7 Seconds      Memory Limit: 65536 KB Patchouli Knowledge, the u ...

  9. 自然数拆分(完全背包问题求方案数)

    给定一个自然数N,要求把N拆分成若干个正整数相加的形式,参与加法运算的数可以重复. 注意: 拆分方案不考虑顺序: 至少拆分成2个数的和. 求拆分的方案数 mod 2147483648的结果. 输入格式 ...

最新文章

  1. ASP.NET中的母版页
  2. UIPickerView 修改必须滚动才修改值的bug
  3. 《Programming WPF》翻译 第7章 3.笔刷和钢笔
  4. 微软欢迎所有热爱开源软件的朋友们来投稿![征稿开放时间:2015年8月17日]
  5. sql查询每个学生的最高成绩mysql语句
  6. Techparty-广州Javascript技术专场(学习分享)
  7. 什么情况下会用到try-catch
  8. java高并发(十四)ReetrantLock 与锁
  9. 阿里程序员深夜智救31楼跳楼邻居
  10. python3怎么使用pyrex_用户指南 - Cython 和 Pyrex 之间的区别 - 《Cython 3.0 中文文档》 - 书栈网 · BookStack...
  11. oracle数据库11g完全卸载,oracle 11g完全卸载
  12. 5年数据总监主动辞职:那些没用可视化报表的人,后来都怎么样了
  13. Exchange企业实战技巧(18)日志规则应用之审计邮箱
  14. WIZnet开源平台ioPlatform所趋,全硬件TCP/IP尽显内芯智慧!
  15. Spark内核解析之四:Spark 任务调度机制
  16. Dojo学习2 dojo快速安装
  17. 单项选择题标准化考试系统设计c语言报告,C语言课程设计(单项选择题标准化考试系统)报告...
  18. 远程计算机桌面图标不见了怎么办,远程桌面图标不见了怎么办
  19. prolog寻找三角形个数
  20. 机器人聊天软件c#_用C#开发MSN插件程序(比如聊天机器人)

热门文章

  1. 前端——面试(熊猫优选)
  2. iPhone又出新机了,UI设计师该用什么尺寸呢?
  3. bzoj1191[HNOI2006] 超级英雄Hero
  4. [深度学习] loss=inf
  5. ViewState的用法
  6. 暾盛机器人_智能化引领发展 品牌化彰显特色——2018台州黄岩(国际)模塑产业博览会侧记...
  7. shp面要素wgs84坐标转火星坐标(gcj)方法
  8. PHP工程师零基础入门到就业班
  9. divcss布局模板代码_(带手机版数据同步)天花板循环扇类网站织梦模板 小家电电器类网站源码下载...
  10. matlab中如何标记点